SpringBoot中如何使⽤Convert接⼝实现类型转换器
⽬录
使⽤Convert接⼝实现类型转换器
Converter接⼝
添加依赖
实体类
1.User类
2.Article类
配置类型转化器
1.定义全局⽇期转换器
2.定义全局对象转换器
3.定义全局List类型转换器
控制器
测试
Converter使⽤及其原理
配置⽂件中对Converter的引⽤
以字符串去空为例
我们查看Converter接⼝的源码
我们查看对应的成员变量:
使⽤Convert接⼝实现类型转换器
在Spring3中引⼊了⼀个Converter接⼝,它⽀持从⼀个Object转为另⼀个Object。除了Converter接⼝之外,实现ConverterFactory接⼝和GenericConverter接⼝也可以实现我们⾃⼰的类型转换逻辑。Converter接⼝
⾸先看看Converter接⼝的定义
public interface Converter<S, T> {
T convert(S source);
}
可以看到这个接⼝是使⽤了泛型的,S表⽰原类型,T表⽰⽬标类型,然后⾥⾯定义了⼀个convert⽅法,将原类型对象作为参数传⼊进⾏转换之后返回⽬标类型对象。
下⾯在Spring Boot中使⽤Converter接⼝来实现将String类型分别转换为Data,⾃定义对象和List<⾃定义对象>。
添加依赖
添加spring-boot-starter-web依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
实体类
1.User类
public class User {
private long  id;
//⽤户名
private String name;
//出⽣⽇期
private Date birth;
//关联⽤户
private User linkUser;
//喜欢的⽂章
private List<Article> favArticles=new ArrayList<>();
//下⾯省略Getter和Setter⽅法
2.Article类
public class Article {
//⽂章id
private long artId;
//⽂章名
private String artName;
//下⾯省略Getter和Setter⽅法
}
配置类型转化器
下⾯三个类都需要添加@Component注解,否则不能⽣效。并实现Spring提供的verter.Converter接⼝,重写其中的convert()⽅法,⽅法中写⾃⼰的转换逻辑。
1.定义全局⽇期转换器
@Component
public class DateConvert implements Converter<String,Date> {
//⽇期格式
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date convert(String s) {
if (s!=null&&!"".equals(s)){
try {
//解析参数
Date date=sdf.parse(s);
return date;
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
}
2.定义全局对象转换器
这⾥使⽤Jackson的ObjectMapper类的readValue()函数实现将Json字符串反序列化为Java对象
@Component
public class ObjectConvert implements Converter<String,User> {
@Override
public User convert(String s) {
ObjectMapper objectMapper=new ObjectMapper();
if (s!=null&&!"".equals(s)){
try {
User adValue(s,User.class);
return user;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
return null;
}
}
3.定义全局List类型转换器
这⾥使⽤Jackson的ObjectMapper类的readValue()函数实现将Json字符串反序列化为 List
@Component
public class StringToListController implements Converter<String, List<Article>> {
ObjectMapper objectMapper=new ObjectMapper();
@Override
public List<Article> convert(String s) {
List<Article> list=null;
try {
adValue(s, new TypeReference<List<Article>>() {
});
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return list;
}
}
控制器
这⾥注意使⽤produces设置返回数据的类型为json,consumes设置提交内容的类型为:application/x-www-form-urlencoded。
application/x-www-form-urlencoded作⽤:将键值对的参数⽤&连接起来,如果有空格,将空格转换为+加号;有特殊符号,将特殊符号转换为ASCII HEX值。@RestController
public class HelloController {
@GetMapping("hello")
public Date getDate(Date birth){
System.out.println(birth);
return birth;
}
@PostMapping(value="showUser",produces="application/json",
consumes = "application/x-www-form-urlencoded")
public User showUser(User user){
return user;
}
}
测试
在Postman中进⾏测试,注意以下设置:POST请求 -> Body -> x-www-form-urlencoded。在Body中输⼊参数进⾏测试。
因为参数中有Json类型参数,如果直接使⽤Params下进⾏发送数据,会出现请求参数异常错误。
测试结果:
Converter使⽤及其原理
在Spring MVC开发中,我们可以很⽅便的使⽤Converter来实现对请求参数的处理,⽐如字符串去空,⽇期格式化等。
配置⽂件中对Converter的引⽤
<!-- 属性编辑器 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="verter.StringTrimConverter" />
<bean class="verter.DateConverter" />
<bean class="verter.DatetimeConverter" />
</list>
</property>
</bean>
<mvc:annotation-driven conversion-service="conversionService">
如上代码,我们配置了三种类型的Converter。
以字符串去空为例
import verter.Converter;
/**
* 去除前后空格
* @author
*
*/
public class StringTrimConverter implements Converter<String, String> {
public String convert(String source) {
//如果源字符串不为空则进⾏转换
if(source != null){
//去除源字符串前后空格
source = im();
if(source.equals("")){
source = null;
}
}
return source;
}
}
配置好以上内容,即可在我们的请求中实现字符串⾃动去空格。
明⽩使⽤其实很简单,我们可以看下在Spring的底层,具体是如何实现Converter的。我们以字符串去空的代码为例。
以上代码,⾸先实现了Converter接⼝
我们查看Converter接⼝的源码
/**
* A converter converts a source object of type S to a target of type T.
* Implementations of this interface are thread-safe and can be shared.
*
* <p>Implementations may additionally implement {@link ConditionalConverter}.
*
* @author Keith Donald
* @since 3.0
* @see ConditionalConverter
* @param <S> The source type
* @param <T> The target type
*/
public interface Converter<S, T> {
/**
* Convert the source of type S to target type T.
* @param source the source object to convert, which must be an instance of S
* @return the converted object, which must be an instance of T
* @throws IllegalArgumentException if the source could not be converted to the desired target type
springframework依赖*/
T convert(S source);
}
通过JavaDoc我们可以看到,实现该接⼝,可以使我们将S类型的对象转换为T类型。那么对应的我们对于Date类型的转换,就可写为如下代码:public class DateConverter implements Converter
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
该类的对象,继续查看对应改类的源码,以及对应的JavaDoc。我们可以在该类的Doc中看到如下描述:
* <p>Like all {@code FactoryBean} implementations, this class is suitable for
* use when configuring a Spring application context using Spring {@code <beans>}
* XML. When configuring the container with
* {@link t.annotation.Configuration @Configuration}
* classes, simply instantiate, configure and return the appropriate
* {@code FormattingConversionService} object from a
* {@link t.annotation.Bean @Bean} method.
该类适⽤于适⽤XML构建Spring应⽤。
我们查看对应的成员变量:
public class FormattingConversionServiceFactoryBean
implements FactoryBean<FormattingConversionService>, EmbeddedValueResolverAware, InitializingBean {
private Set<?> converters;
private Set<?> formatters;
private Set<FormatterRegistrar> formatterRegistrars;
private boolean registerDefaultFormatters = true;
private StringValueResolver embeddedValueResolver;
private FormattingConversionService conversionService;
在配置XML时,我们主要配置了集合类的converters,该类⽐较重要的⽅法如下:
@Override
public void afterPropertiesSet() {
registerFormatters();
}
该⽅法实现了对conversionService中增减我们对应的格式化器。
在Spring启动时,注册转换器时会进⼊afterPropertiesSet ⽅法。在该⽅法中,我们可以看到Spring以HashSet来存储对应的converters。在ConversionServiceFactory中,判断不同的转换器,并进⾏注册。
public static void registerConverters(Set<?> converters, ConverterRegistry registry) {
if (converters != null) {
for (Object converter : converters) {
if (converter instanceof GenericConverter) {
registry.addConverter((GenericConverter) converter);
}
else if (converter instanceof Converter<?, ?>) {
registry.addConverter((Converter<?, ?>) converter);
}
else if (converter instanceof ConverterFactory<?, ?>) {
registry.addConverterFactory((ConverterFactory<?, ?>) converter);
}
else {
throw new IllegalArgumentException("Each converter object must implement one of the " +
"Converter, ConverterFactory, or GenericConverter interfaces");
}
}
}
}
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。