最近在做项目时需要将前台 2018-08-06
格式的字符串传递到 SpringMVC 的 handler 方法的参数中时,转换成日期对象,想到了 SpringMVC 提供了一个转换器接口可以实现这个需求,特此记录一下:
再次看一下 SpringMVC 的执行流程:
在处理数据转换和数据的格式化时一张更加详细的图:
注意第四步,适配器在调用我们编写的 handler 方法时,会先经历如下步骤:
- 将请求的消息转换成指定类型的对象,比如我们的
MappingJackson2HttpMessageConverter
可以将 json 格式的字符串转换成我们指定的实体类对象。 - 然后适配器将 ServletRequest 对象 传递给一个
WebDataBindingFactory
工厂对象来创建一个上图中的DataBinder
对象来进行数据绑定。 DataBinder
对象会调用一个ConversionServiceFactoryBean
工厂 bean 来创建一个ConversionService
对象。ConversionService
对象来对请求中的参数进行数据类型转换和数据的格式化。- 之后
DataBinder
还会再调用 Validator(校验器)进行数据的校验,比如说我们的 Hibernate Validator - 然后
DataBinder
会将参数校验的结果封装进一个 BindingResult 对象里面,这就是我们为什么如果要用校验器进行校验的话需要在参数列表上加一个 BindingResult 参数的原因。 - 参数的预处理工作结束后,再开始执行我们编写的 handler 方法…
我们现在需要做的就是实现一个 Converter 转换器:
-
实现 Converter 接口,注意是 spring 核心包里面的 Converter:
package com.qjl.pems.converter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.core.convert.converter.Converter; /** * 类描述:负责将欠他传递过来的String类型的日期字符串转换成日期对象 * 全限定性类名: com.qjl.pems.converter.DateConverter * @author 曲健磊 * @date 2018年8月15日下午9:55:44 * @version V1.0 */ public class DateConverter implements Converter<String, Date> { /** * 将 yyyy-MM-dd 格式的字符串转换成日期对象 */ @Override public Date convert(String dateStr) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = null; try { date = sdf.parse(dateStr); } catch (ParseException e) { e.printStackTrace(); } return date; } }
-
在 springMVC 的配置文件中配置一个 ConversionServiceFactoryBean ,并注入我们编写好的 Converter 并在 mvc 注解驱动中指明使用 ConversionService:
... <!--开启mvc注解驱动 --> <mvc:annotation-driven conversion-service="conversionService" /> <!-- 注册自定义的类型转换器 --> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.qjl.pems.converter.DateConverter"></bean> </list> </property> </bean> ...
-
看一下 Controller 方法:
/** * 处理添加管理员的请求 * @param admin 前台发送的管理员信息 * @return 添加成功与否的提示信息 */ @RequestMapping("/insertAdmin") public @ResponseBody Map<String, Object> insertAdmin(Admin admin) { Map<String, Object> resultMap = new HashMap<String, Object>(); boolean flag = adminService.insertAdmin(admin); return resultMap; }
Admin 中定义了一个 Date 类型的对象,前台在传送 yyyy-MM-dd 格式的字符串的时候适配器就会去调用我们写好的转换器去自动转换了。
看源码的路径:
- 在Controller 方法中打一个断点并以 Debug 模式启动服务。
- 在 Debug 窗格下找到 DispatcherServlet.doService,点击。
- 在右边找到 handlerAdapters
- 在里面找到 WebBindingInitializer
- 在里面找到 conversionService,这里面就包含了一系列的转换器,其中就有我们配置好的。