关于springMVC 接收date 类型为空时候的异常解决办法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/preferG/article/details/78090669

当我们再试用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 类型数据的操作可以看一下我其他的博客。小白一个,在此献丑啦... 每天进步一点,一年后将会是什么样。


猜你喜欢

转载自blog.csdn.net/preferG/article/details/78090669