org.springframework.validation.BindException异常解决
org.springframework.validation.BindException异常解决
一. 异常现象
我在进行开发平台后台管理项目开发的时候,需要对token进行管理,其中需要对token进行编辑,效果如下:
结果在编辑token的时候,产生了如下现象:
token无法被编辑,阻塞了编辑操作的正常进行!
查看浏览器控制台,发现出现了400状态码:
并且开发工具控制台出现如下异常信息:
[http-nio-8080-exec-22] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'userToken' on field 'expireTime': rejected value [1588986551000]; codes [typeMismatch.userToken.expireTime,typeMismatch.expireTime,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userToken.expireTime,expireTime]; arguments []; default message [expireTime]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'expireTime'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "1588986551000"]
Field error in object 'userToken' on field 'startTime': rejected value [1588468151000]; codes [typeMismatch.userToken.startTime,typeMismatch.startTime,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userToken.startTime,startTime]; arguments []; default message [startTime]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'startTime'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "1588468151000"]]
二. 异常原因
从上面的异常信息中,我提取出核心的异常信息如下:
...Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'expireTime'...nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "1588986551000"
rejected value [1588986551000]; codes [typeMismatch.userToken.expireTime,typeMismatch.expireTime,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userToken.expireTime,expireTime]; arguments []; default message [expireTime]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'expireTime'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "1588986551000"]
从异常信息可以看出,是因为前端页面以字符串形式传递日期时间字符串到后台接口,默认的SpringMVC处理器无法将java.lang.String类型的字符串转换成java.util.Date类型,进而导致IllegalArgumentException: Could not parse date,归根结底就是前端页面中的日期时间字符串与后端JavaBean类中的Date类型不匹配,typeMismatch.userToken.expireTime,typeMismatch.java.util.Date,typeMismatch!
三. 解决办法
解决办法其实有多种,其实只要保证前后端参数可以实现转换就行了,所以基于这种思路,我提供如下几种解决办法。
解决方法一:
在后端的日期类型的字段上,添加如**解:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expireTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
因为我的前端页面,是普通的html页面,且参数是以表单形势传递的,如下:
所以利用@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")注解格式化前端传递进来的日期时间参数形式;
利用@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")格式化后端对外输出的日期时间格式。
解决方法二:
第一种解决方法,需要在每个有日期时间类型字段的类中,都添加那样的2个注解,当代码较多时,就有些麻烦,可以编写一个全局的转换器,代码如下:
package com.yyg.openapi.convert;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author 一一哥
* @Blame yiyige
* @Since Created in 2020/6/29
*/
public class CustomDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return simpleDateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
然后把该类在spring.xml文件中进行注册配置。
<!--全局的日期时间转换器,解决前后端时间类型不匹配而导致的400异常!-->
<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.yyg.openapi.convert.CustomDateConverter"/>
</list>
</property>
</bean>
此时JavaBean类中的属性,只需要格式化对外输出的类型,如下即可:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date expireTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date startTime;