1 转换器的概述
实际上在 SpringMVC 框架中,框架本身就内置了很多类型转换器,这些默认的类型转换器,可以将 String 类型的数据,自动转换为相应类型的数据。这些默认的转换器就在包 org.springframework.core.convert.converter 下,如图所示:

但是有的时候内置的类型转换器不足够满足业务需求,因为默认转换器并不是可以将用户提交的 String 转换为所有用户需要的类型。此时,就需要自定义类型转换器了。
例如,在 Spring MVC 的默认类型转换器中,没有日期类型的转换器,因为日期的格式太多。若要使表单中提交的日期字符串,被处理器方法形参直接接收为日期类型,则需要自定义类型转换器了,否则肯定会报错。
2 转换器实现之实现 Converter 接口
依旧使用前面的提交 Book 举例,首先创建一个实现 Converter 接口的 DateConverter 实现类,代码如下:
package com.thr.convert;
import org.springframework.core.convert.converter.Converter;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
//@Component
public class DateConverter implements Converter<String, LocalDate> {
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd");
public LocalDate convert(String source) {
return LocalDate.parse(source, formatter);
}
}上面是在自定义的参数类型转换器中,将一个前台传来的 String 转为 LocalDate 对象。
然后我们在 Book 类添加一个日期类型的属性,用来表示图书的出版日期,Book 实体类代码如下:
public class Book {
private Integer id;
private String name;
private String publisher;
private LocalDate publishDate;
//getter,setter和toString省略
}接下来,在 SpringMVC 的配置文件(spring-mvc.xml)中配置相关的 Bean 使之生效。
<!-- 注册自定义转换器 -->
<bean id="dateConverter" class="com.thr.convert.DateConverter"/>
<!-- 注册类型转换服务bean -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="dateConverter"/>
</set>
</property>
</bean>
<!-- 配置MVC注解驱动。-->
<mvc:annotation-driven conversion-service="conversionService"/>创建用于提交图书信息的 index.jsp 页面,具体代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<form action="${pageContext.request.contextPath}/book" method="post">
<table>
<tr>
<td>图书ID:</td>
<td><input type="text" name="id" /></td>
</tr>
<tr>
<td>图书名称:</td>
<td><input type="text" name="name" /></td>
</tr>
<tr>
<td>出版社:</td>
<td><input type="text" name="publishingHouse" /></td>
</tr>
<tr>
<td>图书出版日期:</td>
<td><input type="date" name="publishDate" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交" /></td>
</tr>
</table>
</form>
</body>
</html>
3 转换器实现之使用@InitBinder 注解 (推荐)
当然也可以不在 XML 中配置类型转换服务,而是使用 @InitBinder 注解来实现,推荐这种方式。在需要日期转换的 Controller 中使用 SpringMVC 的注解 @InitBinder 和 Spring 自带的 WebDateBinder 类来操作,WebDataBinder 是用来绑定请求参数到指定的属性编辑器。由于前端传到 Controller 里的值是 String 类型的,当往 Model 里 Set 这个值的时候,如果 set 的这个属性是个对象,Spring 就会去找到对应的 editor 进行转换,然后再 SET 进去。
注意:@InitBinder 用于在 @Controller 中标注的方法,表示为当前控制器注册一个属性编辑器,只对当前的 Controller 有效。这个方法会在控制器中其他方法之前调用,这样就可以预先处理数据。
@Controller
public class BookController {
@InitBinder
public void initBinder(WebDataBinder binder) {
//注册原类型和目标类型的转换格式
binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}
});
}
@RequestMapping(value = "book", method = RequestMethod.POST)
public String getInfo(Book book) {
System.out.println(book.getId());
System.out.println(book.getName());
System.out.println(book.getPublisher());
System.out.println(book.getPublishDate());
return "success";
}
}