一、数据绑定

在web应用中,如何将页面的值传递给控制器,是很重要的一个内容,这就是数据绑定。
SpringMVC中的数据绑定非常简单。因为SpringMVC的每个请求指向的都是方法,那么页面的数据直接和方法的形参对应,数据绑定就实现了。常用的数据绑定方式(或者说形参样式)有两种:

  1. 基本类型的数据绑定,如String、int等;
  2. POJO类型的数据绑定。

(一)基本类型的数据绑定

基本类型的数据绑定,使用@RequestParam注解来实现,如下:

@RequestMapping(value="/saveProduct")
public ModelAndView saveProduct(@RequestParam(value="name",required=true) String name,@RequestParam String description,@RequestParam String price){
    product.setName(name);
    product.setDescription(description);
    product.setPrice(price);
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.addObject("product", product);
    modelAndView.setViewName("productDetails");
    return modelAndView;

}

@RequestParam注解的value属性指定了页面传入参数的名称,如果没有指定该属性,则页面传入的参数名称必须和方法的形参名称一样,否则无法接收到值;
required属性指定了页面必须传入该参数,否则就会报错。

(二)POJO类型的数据绑定

POJO类型的数据绑定更加简单了,不需要写任何注解,如下:

@RequestMapping(value="/saveProduct1")
public ModelAndView saveProduct1(Product product){
    logger.info("saveProduct1 been called!");
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.addObject("product", product);
    modelAndView.setViewName("productDetails");
    return modelAndView;
}

因为SpringMVC的每个请求指向的都是方法,所以页面传递值过来时,会去Product类中去寻找相应的属性,如果找不到属性则会报错。注意,POJO类中的属性都必须有相应的getter/setter方法。

在给Product类添加Date类型的createTime属性之前,上述过程是没有问题的。但是,在添加了createTime属性之后,就会报错,报错的原因是:web应用中,从页面传递回来的数据都是String类型的,进行数据绑定时如果类型不同就会报错。这里就涉及到了类型转换。

二、类型转换

在SpringMVC中,类型转换有两种方法。

(一)Converter

Converter是一个接口,实现了该接口的类可以将任意类型转换成另一种指定的类型的对象。下面的StringToDateConverter类可以将字符串类型转换成Date类型。

package converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;

public class StringToDateConverter implements Converter<String,Date> {
    @Override
    public Date convert(String dateString) {
        // TODO Auto-generated method stub
        SimpleDateFormat date = new SimpleDateFormat("YYYY-MM-DD HH:mm:ss");
        try {
            return date.parse(dateString);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

要使用Converter,需要在SpringMVC的配置文件(在本例中时springmvc1.xml)做如下配置:

<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 配置转换器Converter -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="converter.StringToDateConverter"></bean>
        </list>
    </property>
</bean>

(二)Formatter

Formatter只能将String类型转换成其他指定类型的对象。因为web层中,页面传递的都是String类型的,所以Formatter是适合的。下面的类同样将字符串转换成Date类型的对象。

package formatter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import org.springframework.format.Formatter;

public class DateFormatter implements Formatter<Date> {

    @Override
    public String print(Date date, Locale arg1) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Date parse(String dateStr, Locale local) throws ParseException {
        // TODO Auto-generated method stub
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try{
            return sdf.parse(dateStr);
        }
        catch(Exception e){
            e.printStackTrace();
        }
        return null;

    }
}

要使用Formatter,需要在SpringMVC的配置文件(在本例中时springmvc1.xml)做如下配置:

<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 配置转换器Formatter -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="formatters">
        <list>
            <bean class="formatter.DateFormatter "></bean>
        </list>
    </property>
</bean>

三、神奇的<mvc:annotation-driven />

前面的博客中有讲到,<mvc:annotation-driven></mvc:annotation-driven>做了很多事情,其中就包括了两种类型转换:数字类型转换和日期/时间类型转换。
这里推荐一篇博客,讲得很全面:
如果只是将String类型转换成数字(int/long/double等类型)或者Date类型,完全可以不写上面的Converter和Formatter,直接在相应的属性上添加注解即可,如下:

package model;

import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;
import org.springframework.format.annotation.NumberFormat.Style;
import org.springframework.stereotype.Component;

@Component("product")
public class Product {
    private String name;
    private String description;
    private String price;
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    @NumberFormat(style=Style.NUMBER)
    private int id;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

}

如有错误之处,还望留言指正。