`
qq466862016
  • 浏览: 128418 次
  • 来自: 杭州
社区版块
存档分类
最新评论

SpringMVC 日期参数转换报错问题最终解决方案

阅读更多

在用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做的如此强大,给我们更好的扩展接口这样我们不光可以解决日期类型错误,我们还可以把当前登录用户信息当做方法参数等等。


2
2
分享到:
评论

相关推荐

    springmvc创建文件报错解决方案

    这是一个可以运行的ecplise中的mvc题目:从index.jsp跳转到success.jsp。

    解决springmvc关于前台日期作为实体类对象参数类型转换错误的问题

    解决SpringMVC关于前台日期作为实体类对象参数类型转换错误的问题有多种方法,下面我们将介绍三种解决方案。 解决方案1:使用@DateTimeFormat注解 在对应的实体类属性上加入@DateTimeFormat(pattern = "yyyy-MM-dd...

    SpringMVC中后台转换json格式

    本文将详细介绍如何在SpringMVC中后台转换JSON格式,以解决406错误问题。 406错误通常发生在客户端发送了Accept头,表明它期望接收某种特定类型的数据,但服务器无法提供这种类型的数据。在Ajax请求中,这个Accept...

    SpringMVC数据类型转换超详细介绍

    从Spring 3开始,SpringMVC引入了更为强大的数据绑定框架,解决了上述问题,并提供了更加灵活和强大的数据转换、验证及格式化能力。 ##### 1. 类型转换 - **核心组件**:`ConversionService`接口及其具体实现类`...

    SPRINGMVC 406问题解决方案

    SPRINGMVC 406问题解决方案 SPRINGMVC 是一个基于 Java 的 Web 应用程序框架,它提供了一个灵活的方式来开发 Web 应用程序。然而,在使用 SPRINGMVC 时,可能会遇到一些问题,例如 406 错误。本文将详细介绍 ...

    Springmvc自定义参数转换实现代码解析

    SpringMVC自定义参数转换实现代码解析 在 SpringMVC 框架中,参数绑定是指将 HTTP 请求中的参数绑定到控制器的方法参数上。SpringMVC 提供了多种参数绑定的方式,包括默认的参数绑定、简单类型参数绑定、POJO 类型...

    Spring MVC不能直接接收list类型参数的问题

    针对上述问题,有两种主要的方法可以解决 Spring MVC 无法直接接收 List 类型参数的问题: ##### 方法一:使用 jQuery 的 traditional 参数 在 AJAX 请求中添加 `traditional: true` 参数,以确保数组类型的参数被...

    SpringMVC简介与多线程解决方案

    ### 多线程解决方案 在Java中,多线程是实现并发执行任务的关键。SpringMVC提供了一种在服务层实现多线程的方法,以提高程序的执行效率和响应速度。以下是一些关键概念: 1. **ThreadPoolTaskExecutor**:Spring...

    SpringMVC Tomcat控制台乱码问题解决方案

    SpringMVC Tomcat控制台乱码问题解决方案 本文主要介绍了SpringMVC Tomcat控制台乱码问题解决方案,该解决方案通过示例代码进行了详细的介绍,对大家的学习或者工作具有一定的参考学习价值。下面将对该解决方案进行...

    java,html,jquery,js各种报错解决方案

    在IT行业中,编程语言的错误...总的来说,这个压缩包提供了丰富的资源,帮助开发者在遇到各类技术问题时找到解决方案,提升他们的编程技能和问题解决能力。通过深入学习和实践,可以有效提高开发效率,降低项目风险。

    springmvc入门参数绑定ssm整合

    SpringMVC参数绑定是指将用户请求的参数绑定到控制器的方法参数中。例如,使用@PathVariable注解绑定URL中的参数,使用@RequestParam注解绑定请求参数。 五、SSM整合 SSM整合是指将SpringMVC、MyBatis和Spring框架...

    Http请求传参SpringMVC接收参数详细解析

    问题2:前端参数未转换为JSON格式,会导致403错误。需使用`JSON.stringify()`将JavaScript对象转化为JSON字符串。 3. 传数组参数 在POST请求中,可以使用@RequestParam接收数组。当数组作为请求参数时,需要在参数...

    SpringMVC日期类型接收空值异常问题解决方法

    SpringMVC 日期类型接收空值异常问题解决方法 SpringMVC 框架中,日期类型接收空值异常问题是一个常见的问题。这个问题的出现是因为 SpringMVC 框架在接收到空字符串时,无法自动将其转换为 Date 类型。解决这个...

    SpringMVC 传日期参数到后台的实例讲解

    在 SpringMVC 中,有两种方式可以实现日期参数的传递,一种是使用注解的方式,另一种是使用类型转换的方式。 使用注解的方式 在使用注解的方式中,我们需要在 Controller 层中使用 `@InitBinder` 注解来实现日期...

    SpringMVC自定义参数绑定实现详解

    参数绑定过程主要介绍了SpringMVC参数绑定的机理和使用@RequestParam注解指定request请求的参数名绑定到哪个方法形参上。自定义参数绑定部分主要介绍了使用WebDataBinder和使用WebBindingInitializer两种方式实现...

    SpringMVC请求/响应乱码问题解决方案解析

    "SpringMVC请求/响应乱码问题解决方案解析" SpringMVC请求/响应乱码问题是指在使用SpringMVC框架进行Web开发时,请求参数或响应内容出现乱码的问题。这种问题的出现是由于字符编码的不一致所引起的。本文将详细介绍...

    springMVC解决中文乱码

    SpringMVC解决中文乱码问题 SpringMVC 框架中,中文乱码问题是常见的问题之一。解决这个问题的关键是正确地配置字符编码。下面我们将详细介绍 SpringMVC 中解决中文乱码问题的思路和方法。 配置文件中的字符编码 ...

    springmvc接收参数为日期类型

    三、解决日期类型转换问题 1. **使用`@InitBinder`方法** `@InitBinder`注解用于初始化数据绑定过程,我们可以在这个方法中添加自定义的日期格式化器。例如,我们可以创建一个全局的日期格式: ```java @...

    SpringMVC上传文件ie提示下载json文件解决方案

    解决这个问题的关键在于正确配置SpringMVC中的消息转换器,确保它能够正确处理文件上传请求并返回正确的响应类型。以下是一种可行的解决方案: 1. **配置消息转换器**: 在SpringMVC配置文件中,需要配置一个消息...

Global site tag (gtag.js) - Google Analytics