在用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做的如此强大,给我们更好的扩展接口这样我们不光可以解决日期类型错误,我们还可以把当前登录用户信息当做方法参数等等。
相关推荐
在SpringMVC框架中,日期类型的参数转换是常见的问题之一。当我们在实体类中使用java.util.Date类型的属性时,可能会出现类型转换错误的问题。在本文中,我们将探讨解决SpringMVC关于前台日期作为实体类对象参数类型...
另一种解决方案是创建一个专门的对象来封装列表参数。首先定义一个 VO (Value Object) 类,其中包含 `List<String>` 类型的属性。 **VO 定义示例**: ```java public class ParamVo { private List<String> ...
springMVC ResponseBody 返回汉字乱码解决方案 在使用 SpringMVC 时,可能会出现汉字乱码错误。解决方法是,使用 SpringMVC 的编码过滤器,确保响应体的编码正确,并且确保视图文件的编码正确。 springboot 提示...
目的主要有两个,其一生封装微信请求xml消息为java实体对象,将返回对象转换为xml响应消息;其二是封装微信接口为java服务。微信公众号采用web服务作为消息与第三方平台发生交互,数据格式主要是xml和json,普通的...
### 自整理Java关于基础和框架的面试题 #### 基础知识点 ##### JDK常用的包 - **java.lang**: 包含所有基本类,如`String`、`Math`等。...- Spring是一个开源框架,提供了一整套的企业级服务解决方案...
- **Hibernate**:全ORM解决方案,自动管理对象的生命周期。 - **MyBatis (原Ibatis)**:半ORM框架,提供动态SQL支持。 - **JDBC**:直接与数据库交互,灵活性高但编码繁琐。 ##### Hibernate的运行原理 - **...