自定义类型转换器
# 50.自定义类型转换器
前端传值全都是字符串,但是 SpringMVC 会自动帮我们转换数据,例如字符串转 double,转日期等;但是可能会有格式问题,例如英文字母转数字肯定是不行的; 还有如果日期的字符串格式不对,转换也会失败。因此我们可以自定义转换器
# 新建 JavaBean
我们新建一个类 User2,包含日期类型的:
public class User2 implements Serializable {
private String uname;
private Integer age;
private Date date;
}
2
3
4
5
6
这里省略 setter、getter 和 toString 方法
# 新增表单
在 param.jsp 中新建一个表单
<form action="param/saveUser" method="post">
User姓名:<input type="text" name="uname" /> <br/>
User年龄:<input type="text" name="age" /> <br/>
User生日:<input type="text" name="date" /> <br/>
<input type="submit" value="提交" />
</form>
2
3
4
5
6
# 新建控制器方法
我们在 ParamController
类中新增方法:
@RequestMapping("/saveUser")
public String saveUser(User2 user2) {
System.out.println("saveUser");
System.out.println(user2);
return "success";
}
2
3
4
5
6
# 测试
此时我们日期分隔符是斜线,是能正常提交的,后台输出:
User2{uname='peter', age=11, date=Fri May 20 00:00:00 CST 2022}
如果用减号:报错了,并且后台也没打印 User2 对象,因为是在类型转换的时候出现了问题
# 解决方法
为了解决类型转换的问题,SpringMVC 可以让我们自定义类型转换器,就是自己写一个类,实现一个接口,然后定义一个方法去转换类型;
然后需要注册这个类,因为 SpringMVC 是基于组件的,我们写完后要注册一个类型转换器,注册成功后,前端控制器就会去寻找这个类型转换器
我们需要实现的这个接口:
package org.springframework.core.convert.converter;
import org.springframework.lang.Nullable;
public interface Converter<S, T> {
/**
* Convert the source object of type {@code S} to target type {@code T}.
* @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
* @return the converted object, which must be an instance of {@code T} (potentially {@code null})
* @throws IllegalArgumentException if the source cannot be converted to the desired target type
*/
@Nullable
T convert(S source);
}
2
3
4
5
6
7
8
9
10
11
12
13
我们可以看看其实现类:
可以看到有很多,例如字符串转布尔类型,字符串转 TimeZone 类型等等。其实我们不用自定义也行,这里主要是为了演示才自定义。
# 新建转换器
新建一个类,实现转换器接口:
package com.peterjxl.util;
import org.springframework.core.convert.converter.Converter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class StringToDateConverter implements Converter<String, Date>{
@Override
public Date convert(String source) {
if (source == null){
throw new RuntimeException("请您输入日期");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(source);
} catch (Exception e) {
throw new RuntimeException("数据类型转换出现错误");
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 配置转换器
我们在 springmvc.xml 中新增如下配置:
<!-- 注册自定义类型转换器-->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.peterjxl.util.StringToDateConverter"/>
</set>
</property>
</bean>
2
3
4
5
6
7
8
9
然后我们使用一个新的标签 mvc:annotation-driven
,配置让这个类型转换器生效:
<!-- 开启SpringMVC注解驱动 -->
<mvc:annotation-driven conversion-service="conversionService"/>
2
使用 <mvc:annotation-driven>
可以自动加载 RequestMappingHandlerMapping (处理映射器) 和 RequestMappingHandlerAdapter ( 处 理 适 配 器 ),因此一般开发中,我们都需要写上此标签。目前用的比较少,但随着课程的深入,该标签还有具体的使用场景
# 再次测试
我们重启服务,再次提交表单,可以看到能正常转换数据了
# 源码
本项目已将源码上传到 GitHub (opens new window) 和 Gitee (opens new window) 上。并且创建了分支 demo4,读者可以通过切换分支来查看本文的示例代码。