软件编程
位置:首页>> 软件编程>> java编程>> Spring Boot中如何使用Convert接口实现类型转换器

Spring Boot中如何使用Convert接口实现类型转换器

作者:Code0cean  发布时间:2023-05-09 20:28:37 

标签:SpringBoot,Convert,类型转换

使用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提供的org.springframework.core.convert.converter.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 user=objectMapper.readValue(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 {
      list=objectMapper.readValue(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下进行发送数据,会出现请求参数异常错误。

Spring Boot中如何使用Convert接口实现类型转换器

测试结果:

Spring Boot中如何使用Convert接口实现类型转换器

Converter使用及其原理

在Spring MVC开发中,我们可以很方便的使用Converter来实现对请求参数的处理,比如字符串去空,日期格式化等。

配置文件中对Converter的引用


<!-- 属性编辑器 -->
   <bean id="conversionService"
       class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
       <property name="converters">
           <list>
               <bean class="com.xxx.common.converter.StringTrimConverter" />
               <bean class="com.xxx.common.converter.DateConverter" />
               <bean class="com.xxx.common.converter.DatetimeConverter" />
           </list>
       </property>
   </bean>
<mvc:annotation-driven conversion-service="conversionService">

如上代码,我们配置了三种类型的Converter。

以字符串去空为例


import org.springframework.core.convert.converter.Converter;
/**
* 去除前后空格
* @author
*
*/
public class StringTrimConverter implements Converter<String, String> {
   public String convert(String source) {
       //如果源字符串不为空则进行转换
       if(source != null){
           //去除源字符串前后空格
           source = source.trim();
           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
    */
   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 org.springframework.context.annotation.Configuration @Configuration}
* classes, simply instantiate, configure and return the appropriate
* {@code FormattingConversionService} object from a
* {@link org.springframework.context.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() {
       this.conversionService = new DefaultFormattingConversionService(this.embeddedValueResolver, this.registerDefaultFormatters);
       ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
       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");
               }
           }
       }
   }

来源:https://blog.csdn.net/huangjhai/article/details/104214894

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com