在表单提交的任何数据类型全都是字符串类型,后台在接收到请求之后,Spring框架内部的HandlerAdapter 会默认进行数据类型转换。但是如果其中包含了非基本数据类型,例如在用户表单中需要用户的生日,则HandlerAdapter 无法将 String类型自动转换成 Date类型的,此时需要实现 Converter接口来辅助 Spring MVC完成数据类型转换。先来看不使用自定义的类型转换器的效果,实现步骤如下:
(1)创建实体类
public class User {
private String name;
private String password;
private Integer age;
private Date birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
}
(2)在index.jsp中加入用户表单。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form method="post" action="${pageContext.request.contextPath}/user/login">
姓名:<input type="text" name="name"><br>
密码:<input type="text" name="password"><br>
年龄:<input type="text" name="age"><br>
生日:<input type="text" name="birthday"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
(3)创建UserController类
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login")
public String login(User user){
System.out.println(user);
return "success";
}
}
(4)success.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>SUCCESS</h3>
</body>
</html>
启动项目,在页面输入信息并点击提交,此时在页面中输入的生日格式为1997/12/12。
但是如果输入1997-10-10,此时数据就会封装错误,如下:
Spring MVC中提供了Converter<S,T> ,可以将一种数据类型转换成另一种数据类型的接口,这里 S 表示源类型,T 表示目标类型。实现过程如下:
(1)自定义类型转换器,实现接口
public class MyDateConverter implements Converter<String, Date> {
@Override
public Date convert(String s) {
if(s == null){
throw new RuntimeException("日期数据为空");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try{
return df.parse(s);
}catch (Exception e){
throw new RuntimeException("日期数据转换失败");
}
}
}
(2)在springmvc.xml中加入配置
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"></mvc:annotation-driven>
<!-- 注册自定义类型转换器 -->
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.yht.example1.utils.MyDateConverter"></bean>
</set>
</property>
</bean>
此时再在页面输入1997-12-12,则运行成功,如下:
需要注意的是两种格式:1997/12/12和1997-12-12。前面介绍了Spring MVC框架可以自动将1997/12/12映射为pojo对象的日期类型,但是无法将1997-12-12进行映射,所以我们使用了自定义类型转换器来处理1997-12-12该格式的输入数据,但是当自定义的类型转换器起作用之后,原来的1997/12/12这种格式的日期则无法映射成功。我简单查看了一下ConversionServiceFactoryBean的源码,觉得问题出在set方法里,如下:
我个人认为在配置文件中通过property对converters属性进行了赋值,而使得原来的Spring MVC中默认进行的类型转换操作被覆盖掉了。我使用的spring mvc中的jar包都是4.2.3版本,是否在低版本中该类的实现方式不同,还有待后续深入研究。
目前查阅了大量博客还没找到能够同时使用这两种格式的方案,如果有小伙伴找到了,可以评论,大家共同进步。
关于日期格式化,在Spring MVC中还有一个注解@DateTimeFormat(pattern = "yyyy-MM-dd"),只需要将该注解加在User类的birthday属性之上即可,如果里面pattern是yyyy-MM-dd,则支持1997-12-12格式。如果pattern是yyyy/MM/dd,则支持1997/12/12。