在用Springmvc的日期类型作为参数的时候,会碰到
org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type ' java.lang.String' to required type 'java.util.Date'; nested exception is java.lang. IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date]: no matchingeditors or conversion strategy found 对应不能绑定问题一般有下面几个方法: 一、Spring3的源码,略微做了下修改:在Spring3的core包下找到
org.springframework.core.convert.support.GenericConversionService.convert(Object, TypeDescriptor, TypeDescriptor);这个方法然后在assertNotNull(sourceType, targetType);
这个方法然后在assertNotNull(sourceType, targetType); 这句话的下面添加:
if(targetType.getType().getName().equals("java.util.Date")
&& source instanceof String){
String date = (String)source;
try {
source = YMD_DATETIME_FORMAT.parse(date);
} catch (ParseException e) {
try {
source = YMDHM_DATETIME_FORMAT.parse(date);
} catch (ParseException e1) {
try {
source = YMDHMS_DATETIME_FORMAT.parse(date);
} catch (ParseException e2) {
source = null;
}
}
}
sourceType = targetType;
}
最后重新编译打包core包 这样当遇到Date类型的时候就把数据转换成Date类型的,接下去就不会报错了 这种方法不推荐,修改了源代码,日期类型格式非灵活性。不建议采用 二、在mvc配置的那个xml中添加如下代码:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="cacheSeconds" value="0" /> <property name="webBindingInitializer"> <bean class="WebBinding" /> </property> </bean>
添加WebBinding
import java.util.Date;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.context.request.WebRequest;
public class WebBinding implements WebBindingInitializer {
@Override
public void initBinder(WebDataBinder binder, WebRequest request) {
// 使用spring自带的CustomDateEditor
// 解决时间转换问题
// yyyy-MM-dd
binder.registerCustomEditor(Date.class,
new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
}
这样虽然可以解决日期类型参数报错问题也不建议采用,这样每个日期类型格式必须 yyyy-MM-dd 三、采用自定义注解方式解决日期类型参数绑定问题 1、 定义一个自定义日期类型解析器注解
package org.dongtian.sys.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 日期类型解析器注解
* @author gaoyuandong
* @mailto 466862016@qq.com
* @date 2015年9月6日 下午2:18:38
*/
@Target({ElementType.PARAMETER,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DateParser {
//名称
String name() default "";
//格式化
String pattern() default "yyyy-MM-dd hh:mm:ss";
}
默认格式为 yyyy-MM-dd hh:mm:ss 2、接下来我们定义一个此日期类型解析器注解对应的解析器(我们实现Springmvc自定义方法参数解析器)
package org.dongtian.sys.web.context;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dongtian.sys.annotation.DateParser;
import org.springframework.beans.BeanUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/***
* spring mvc 方法参数或者参数为bean中包含有日期类型的格式解析器
* @author gaoyuandong
* @mail 466862016@qq.com
* @date 2015年9月13日 下午3:49:39
*/
public class DateHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
private static Logger log = Logger.getLogger(DateHandlerMethodArgumentResolver.class);
public boolean supportsParameter(MethodParameter parameter) {
//方法参数
DateParser dateParser = parameter.getParameterAnnotation(DateParser.class);
if (dateParser != null) {
return true;
} else { //bean的字段上是否存在@DateParser注解
Class<?> targetType = parameter.getParameterType();
Field[] fields = targetType.getDeclaredFields();
if(fields != null && fields.length >0) {
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if(field.isAnnotationPresent(DateParser.class) == true) {
return true;
}
}
}
return false;
}
}
/***
* 解析包含有{@link org.dongtian.sys.annotation.DateParser} 注解的参数
*/
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
if(binderFactory == null) return null;
if(this.findDateParserAnnotationWithArguement(parameter) == true) {
return this.handlerMethodArgumentDateParserAnnotation(parameter,mavContainer,webRequest,binderFactory);
} else {
return this.handlerBeanArgumentDateParserAnnotation(parameter,mavContainer,webRequest,binderFactory);
}
}
/***
* 解析bean中成员变量 中包含有{@link org.dongtian.sys.annotation.DateParser} 注解的参数
* @author gaoyuandong
* @date 2015年9月13日 下午4:39:58
* @param parameter
* @param mavContainer
* @param webRequest
* @param binderFactory
* @return
*/
private Object handlerBeanArgumentDateParserAnnotation(MethodParameter parameter,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
Class<?> targetType = parameter.getParameterType();
Object obj = BeanUtils.instantiate(targetType);
Field[] fields = targetType.getDeclaredFields();
WebDataBinder binder;
try {
binder = binderFactory.createBinder(webRequest, null, obj.getClass().getName());
for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName();
Class<?> fieldType = field.getType();
Object arg = null;
if(!Modifier.isFinal(field.getModifiers())) {
if(!StringUtils.isBlank(webRequest.getParameter(fieldName))) {
if(field.isAnnotationPresent(DateParser.class)) {
DateParser dateParser = field.getAnnotation(DateParser.class);
String pattern = dateParser.pattern();
String key = StringUtils.isBlank(dateParser.name()) ? parameter.getParameterName() : dateParser.name();
//TODO
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
Date date = dateFormat.parse(webRequest.getParameter(fieldName));
arg = date;
} else {
arg = binder.convertIfNecessary(webRequest.getParameter(fieldName), fieldType, parameter);
}
} else {
arg = getDefaultArgumentValue(fieldType, arg);
}
field.set(obj, arg);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
return obj;
}
/***
* 获取基本数据类型默认的值
* @author gaoyuandong
* @date 2015年9月13日 下午5:27:37
* @param fieldType
* @param arg
* @return
*/
private Object getDefaultArgumentValue(Class<?> fieldType, Object arg) {
if(this.isBasicDataType(fieldType)) {
if(fieldType.getName().equals(Boolean.TYPE) ||fieldType.getName().equals(Void.TYPE) ) {
} else {
arg = 0;
}
}
return arg;
}
/**
* 判定是否为基本数据类型
* @author gaoyuandong
* @date 2015年9月13日 下午5:12:53
* @param fieldType
* @return
*/
private boolean isBasicDataType(Class<?> fieldType) {
return fieldType.isPrimitive()?true:false;
}
/***
* {@link org.dongtian.sys.annotation.DateParser} 注解在方法参数中数据绑定
* @author gaoyuandong
* @date 2015年9月13日 下午4:19:02
* @param parameter
* @param mavContainer
* @param webRequest
* @param binderFactory
* @return
* @throws ParseException
*/
private Object handlerMethodArgumentDateParserAnnotation(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
String[] vals = webRequest.getParameterValues(parameter.getParameterName());
if (vals == null || vals.length == 0) {
return null;
}else {
if (StringUtils.isBlank(vals[0])) {
return null;
} else {
for (Iterator<String> itr = webRequest.getParameterNames(); itr.hasNext();) {
String next = itr.next();
log.debug(next + " : " + webRequest.getParameterValues(next)[0]);
}
DateParser dateParser = parameter.getParameterAnnotation(DateParser.class);
String pattern = dateParser.pattern();
String key = StringUtils.isBlank(dateParser.name()) ? parameter.getParameterName() : dateParser.name();
// TODO
log.debug(parameter.getParameterName());
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
Date date = null;
try {
date = dateFormat.parse(webRequest.getParameterValues(parameter.getParameterName())[0]);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return date;
}
}
}
/***
* 是否存在{@link org.dongtian.sys.annotation.DateParser}注解
* @author gaoyuandong
* @date 2015年9月13日 下午4:14:05
* @param parameter
* @return true 存在 false 不存在
*/
private boolean findDateParserAnnotationWithArguement(MethodParameter parameter) {
return parameter.getParameterAnnotation(DateParser.class) == null ? false:true;
}
}
此类可以解析作用在方法参数上和javabean中的成员变量为date类型上 下面是作用在方法参数上
@RequestMapping("/index")
public ModelAndView index(@DateParser(pattern="yyyy-MM-dd")Date createTime,User user, @RequestParam(defaultValue="1")Integer pageNum,@RequestParam(defaultValue="5")Integer pageSize,String userName,String nickName,String email) {
ModelAndView andView = new ModelAndView("admin/user/index");
System.err.println(user.getCreateTime());
Page<User> page = new Page<User>(pageNum,pageSize);
PageHelper.startPage(page.getPageNum(), page.getPageSize());
List<User> userList = this.userService.findUserList(userName,nickName,email);
int userCount = this.userService.findUserCount(userName,nickName,email);
page.setTotalCount(userCount);
page.setList(userList);
andView.addObject("page", page);
return andView;
}
下面用在java bean上
@RequestMapping("/showDate")
@ResponseBody
public JsonResult showDate(User user) {
return null;
}
package org.dongtian.sys.entity;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.dongtian.sys.annotation.DateParser;
import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 用户信息
* @author gaoyuandong
* @mailto 466862016@qq.com
* @date 2015年8月25日 下午7:45:40
*/
public class User {
private Integer userId;
private String userName;
private String password;
private Integer state;
private int age;
private int sex;
private String address;
private String mobile;
private String email;
private Integer userType;
private String nickName;
@DateParser(pattern="yyyy-MM-dd hh:mm:ss")
private Date createTime;
private Date updateTime;
private Date regTime;
private List<Role> roleList = new ArrayList<Role>();
//正常
public final static int USER_STATE_NORMAL = 0;
//已删除
public final static int USER_STATE_DELETE = 1;
//已经被锁定
public final static int USER_STATE_LOCKED = 2;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
@DateTimeFormat(pattern="yyyy-MM-dd hh:mm:ss")
@JsonFormat(pattern="yyyy-MM-dd hh:mm:ss")
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@DateTimeFormat(pattern="yyyy-MM-dd hh:mm:ss")
@JsonFormat(pattern="yyyy-MM-dd hh:mm:ss")
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@DateTimeFormat(pattern="yyyy-MM-dd hh:mm:ss")
@JsonFormat(pattern="yyyy-MM-dd hh:mm:ss")
public Date getRegTime() {
return regTime;
}
public void setRegTime(Date regTime) {
this.regTime = regTime;
}
public Integer getUserType() {
return userType;
}
public void setUserType(Integer userType) {
this.userType = userType;
}
public List<Role> getRoleList() {
return roleList;
}
public void setRoleList(List<Role> roleList) {
this.roleList = roleList;
}
}
4、最后我们将我们的自定义方法参数解析器在RequestMappingHandlerAdapter配置
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter"/>
</list>
</property>
<property name="customArgumentResolvers">
<list>
<ref bean="dateHandlerMethodArgumentResolver"/>
</list>
</property>
</bean>
<bean id="dateHandlerMethodArgumentResolver" class="org.dongtian.sys.web.context.DateHandlerMethodArgumentResolver"></bean>
这样会更加灵活不得不承认springmcv做的如此强大,给我们更好的扩展接口这样我们不光可以解决日期类型错误,我们还可以把当前登录用户信息当做方法参数等等。