转载请注明出处:http://www.jianshu.com/p/eda34afd9b8a
该文是基于Spring 4.2.3.RELEASE版本展开的
在使用SpringMVC时,从页面传来的字面值要转换为相应格式的属性值,对于String,Integer等最基本的类型,Spring可以自动转换,但是对于像Date这种较为复杂的类型转换,就没有那么容易了。
在Controller中定义如下方法接收页面请求:
@RequestMapping("test")
@ResponseBody
public String test(Date date){
return date.toString();
}
如果在页面访问,http://localhost:8080/test?date=2015-02-04 20:40:38 会报400错误,后台会抛异常:Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'; 这是因为Spring没有默认实现String字面值到Date的转化。
对于上述通过url或者由表单传过来的数据,后台若想成功接收,方法有如下几种:
1.在Controller中自定义initBinder
@InitBinder("date") //注意,这里的date需要与请求中的参数名相同
protected void initBinder(WebDataBinder binder){
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),true));
}
说明:这种方法每次只能处理一个参数,若要处理多个参数,则要写多个,并不灵活
2.自定义Converter或Formatter
自定义DateConverter类
public class DateConverter implements Converter<String, Date> {
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public Date convert(String source) {
try {
return simpleDateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
在xml中引入上述Converter
<bean id="date-converter" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<bean class="young.test.formatter.DateFormatter" />
</set>
</property>
</bean>
annotation-driven中引用
<mvc:annotation-driven conversion-service="date-converter"/>
说明:这种方法是全局的设置,对所有的**@RequestParam 或 @ModelAttribute**的Date类型的绑定都有效
3.使用注解@DateTimeFormat
引入joda包
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9</version>
</dependency>
使用注解修饰相应参数
@RequestMapping("test")
@ResponseBody
public String test(@RequestParam(name = "date") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date1){
return date1.toString();
}
但是通过request body传过来的数据,无法运用上述方法转换
定义如下类:
public class User {
private String name;
private Integer age;
// @JsonDeserialize(using = DateDeserializer.class)
private Date birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
}
Controller:
@RequestMapping(value = "user", method = RequestMethod.POST)
@ResponseBody
public String test2(@RequestBody User user){
return user.toString();
}
直接post请求,后台会报birthday字段转换错误,对于这种类型的参数绑定,一般有如下两种处理方法:
1.自定义DateDeserializer
public class DateDeserializer extends JsonDeserializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String str = jp.getText().trim();
try {
return dateFormat.parse(str);
} catch (ParseException e) {
}
return ctxt.parseDate(str);
}
}
使用@JsonDeserialize(using = DateDeserializer.class)注释相应字段或参数
2.覆盖objectMapper的dateFormat
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss"/>
</bean>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
以上两种方法解决了request body中数据的绑定问题