当我们再试用springMVC搭建后台框架的时候,如果再使用实体类接收参数的时候,难免会碰到时间类型的数据。今天在做项目的时候碰到springMVC 实体bean中存在着Date 类型的参数在前端传递参数中会存在Date类型的数据,当我们在做条件查询的会后难免 会出现Date 数据类型为空的情况,那么此时就会出现 无法找到对应的Mapper 的方法 ,根本就提交不过去,具体浏览器报错为:
此时后台也会给出相应的错误:
org.springframework.web.servlet.DispatcherServlet 2017-09-25 23:19:19 -- INFO -- FrameworkServlet 'mvc': initialization completed in 25367 ms
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver 2017-09-25 23:19:20 -- WARN -- Handler execution resulted in exception: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'userBean' on field 'create': rejected value []; codes [typeMismatch.userBean.create,typeMismatch.create,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userBean.create,create]; arguments []; default message [create]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'create'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @com.fasterxml.jackson.databind.annotation.JsonDeserialize java.util.Date for value ''; nested exception is java.lang.IllegalArgumentException]
最后在网上查找是因为 springMVC将字符串直接认为是Date类型了,可是如果空字符串的话,就不认识了,这有可能是在设计上,有一个小问题吧,我自己认为是这样。
具体决绝办法 :
第一种方式直接在对应的controller中增加属性编辑器:
@InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
注意这块的new CustomDateEditor(dateFormat, true)
中的true,查看CustomDateEditor
源码可以看到:
/**
* Create a new CustomDateEditor instance, using the given DateFormat
* for parsing and rendering.
* <p>The "allowEmpty" parameter states if an empty String should
* be allowed for parsing, i.e. get interpreted as null value.
* Otherwise, an IllegalArgumentException gets thrown in that case.
* @param dateFormat DateFormat to use for parsing and rendering
* @param allowEmpty if empty strings should be allowed
*/
public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty) {
this.dateFormat = dateFormat;
this.allowEmpty = allowEmpty;
this.exactDateLength = -1;
}
当
allowEmpty
字段为true的时候form表单传递的值可以为空。否则会出现
""
字符串解析为date报错。
可是这样的话只能在当前的controller中起到作用, 但我们的controller存在很多并且实体类中的date类型的数据也有很多的话,这样每一个都配置很麻烦。
下面介绍一下
关于@initBinder 对所有 controller 都有效有了解决方案。
利用 @ControllerAdvice注解 。在有此注解的类里 写 @initBinder 方法,并指明目标 类,则可对目标类起作用。
@ControllerAdvice 注解的方式给我们提供了三种方法:
第一种:直接注册到controller 类上 具体代码
@ControllerAdvice(annotations = RestController.class)
public class AnnotationAdvice {}
第二种:直接配置包名自动扫描,具体代码:
@ControllerAdvice("com.cy.ssm")
public class BasePackageAdvice {}
第三种:添加多个controller 集合,具体代码:
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class AssignableTypesAdvice {}
根据自己的业务需求可以进行整合。
在我的程序里面我采用的是第二种方式,这样只需要编写一次,就能够满足需求,我认为没有必要每一个controller多进行配置,这样我们的工作量是一方面,将来改动东西的时候,还有可能忘记,哪里需要更改等问题。
所以我新建了一个class 具体代码如下:
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
@ControllerAdvice("com.cy.ssm")
public class BasePackageAdvice {
@InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
}
如果采用第二种方式的话特别注意的是:springMVC 配置文件中将该类进行扫描 这样才能起到注册的作用,这样每一次请求才能先到我们的@InitBinder中才能起到对字符串的操作
具体代码为:
<context:component-scan base-package="com.cy.ssm.controller" />
到此我们成功的将空的date类型的字符串传递到了后台。
总结:每次请求都会先调用 @ControllerAdvice 类下的 @initBinder 方法。然后再调用 controller的 @requestMapping 对应的方法。
如果想了解更多的springMVC 关于date 类型数据的操作可以看一下我其他的博客。小白一个,在此献丑啦... 每天进步一点,一年后将会是什么样。