SpringMVC Databinding(数据绑定)

2017-10-10  本文已影响0人  我不吃甜食

转载请注明出处: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中数据的绑定问题

上一篇 下一篇

猜你喜欢

热点阅读