Spring Boot中如何使用Convert接口实现类型转换器
作者:Code0cean 发布时间:2023-05-09 20:28:37
使用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下进行发送数据,会出现请求参数异常错误。
测试结果:
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


猜你喜欢
- 由于之前一直在使用spring-boot开发,但一直苦恼于不知道如何利用debug调试代码.在网上查找了很多文章之后。学习之余决定把spri
- 获取Spring中的bean有很多种方式,再次总结一下:第一种:在初始化时保存ApplicationContext对象Application
- 目录Retrofit介绍Retrofit优点Retrofit的使用1.引入依赖项2.添加网络权限3.编写Retrofit辅助类4.定义Api
- 定义广播 * 的Action:private static final String TAG ="SmsService"
- 如下所示:package cn.sunzn.md5;import java.security.MessageDigest;import ja
- 本文实例讲述了C++语言实现线性表之链表实现方法。分享给大家供大家参考。具体分析如下:插入、删除结点的代码有点多,但这样提高了代码的可读性,
- 本文实例讲述了JAVA中AES加密方法。分享给大家供大家参考。具体如下:java代码:KeyGenerator kg = KeyGenera
- 想要实现无限轮播,一直向左滑动,当到最后一个view时,会滑动到第一个,无限…可以自己写ViewPager然后加handler先实现自动滚动
- 一般在web应用中,对客户端提交上来的图片肯定需要进行压缩的。尤其是比较大的图片,如果不经过压缩会导致页面变的很大,打开速度比较慢,影响用户
- 获取方法的相关信息的两种形式反射是一种允许用户获得类信息的C#功能,Type对象映射它代表的底层对象;在.Net 中, 一旦获得了Type对
- 说起EventTrigger事件触发器,它的使用可以说是无处不在,EventTrigger继承了很多的事件接口,这些接口对我们开发是十分有用
- 刚从Eclipse转Intellij,对于它的各种操作也是一脸懵逼,但觉得使用起来还不错,今天就说一下我用Idea导入git中的Maven项
- Apache Shiro官网:https://shiro.apache.org/spring-boot.html.一、依据官网快速搭建Qui
- 一、概述 在C和C++语言中都有assert关键,表示断言。在Java中,同样也有assert关键字,表示断言,用法和含义都差不多
- spring在启动时会自己把bean(java组件)注册到ioc容器里,实现控制反转,在开发人员使用spring开发应用程序时,你是看不到n
- 现在视频应用越来越火,Periscope火起来后,国内也出现了不少跟风者,界面几乎跟Periscope一模一样.Periscope确实不错,
- 先看下利用wheelview实现滚动随机选择号码效果:直接上代码 首页就是dialog显示不在描述 主要看dialog代码package c
- 问题今天遇到一个问题,在下面的代码中,当抛出运行时异常后,后面的代码还会执行吗,是否需要在异常后面加上return语句呢?public vo
- 前言有时候我们在项目中,会用到一些本地 jar 包文件,比如隔壁公司自己打包的;此时无法从maven远程仓库拉取;那么我们可以考虑把 jar
- Android中广播(BroadcastReceiver)的详细讲解.1. BroadcastReceiver的注册过程: (1).广播消息