• Http请求传递的数据都是字符串String类型的,上面这个方法在Controller中定义
  • 如果该方法对应的地址接收到到浏览器的请求的话,并且请求中含有num和birth参数,
  • 那么num会被自动转换成Integer对象;birth会被自动转为Date对象(Date转换需要配置属性编辑器)。

PropertyEditor是属性编辑器的接口

  • 有个方法setAsText很重要。 比如String对象"1"要使用属性编辑器转换成Integer对象,通过setAsText里Integer.parseInt(text)得到Integer对象,然后将Integer对象保存到属性中。
  • 它的基本实现类是PropertyEditorSupport,一般我们要编写自定义的属性编辑器只需要继承这个类即可。
  • Spring中有很多自定义的属性编辑器,都在spring-beans jar包下的org.springframework.beans.propertyeditors包里。

springmvc是如何实现参数的自动收集的

对于String,number(int double float..)以及boolean类型,springmvc会自动将它们与我们的po bean进行绑定

ServletRequestDataBinder

  1. PropertyEditorRegistry接口
    1. 封装方法来给JavaBean注册对应的属性编辑器。
    2. PropertyEditorRegistrySupport:PropertyEditorRegistry接口的基础实现类
      1. PropertyEditorRegistrySupport类有个createDefaultEditors方法,会创建默认的属性编辑器。
    3. TypeConverter接口 类型转换接口。 通过该接口,可以将value转换为requiredType类型的对象。
  2. TypeConverterSupport:TypeConverter基础实现类,并继承了PropertyEditorRegistrySupport

有个属性typeConverterDelegate,类型为TypeConverterDelegate,TypeConverterSupport将类型转换委托给typeConverterDelegate操作。

  1. TypeConverterDelegate

类型转换委托类。具体的类型转换操作由此类完成。

  1. SimpleTypeConverter

TypeConverterSupport的子类,使用了PropertyEditorRegistrySupport(父类TypeConverterSupport的父类PropertyEditorRegistrySupport)中定义的默认属性编辑器。

  1. PropertyAccessor接口

对类中属性操作的接口。

  1. BeanWrapper接口

继承ConfigurablePropertyAccessor(继承PropertyAccessor、PropertyEditorRegistry、TypeConverter接口)接口的操作Spring中JavaBean的核心接口。

  1. BeanWrapperImpl类

BeanWrapper接口的默认实现类,TypeConverterSupport是它的父类,可以进行类型转换,可以进行属性设置。

  1. DataBinder类

实现PropertyEditorRegistry、TypeConverter的类。支持类型转换,参数验证,数据绑定等功能。

有个属性SimpleTypeConverter,用来进行类型转换操作。

  1. WebDataBinder

DataBinder的子类,主要是针对Web请求的数据绑定。

  • 在程序内部,DataBinder实例内部使用一个BeanWrapperImpl实例,负责设置命令对象的值。
  • 通过getPropertyType方法,获取属性类型。
  • 对于request请求,spring将会调用
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(person);
 
Clazz requiredType = beanWrapper.getPropertyType("name");

接下来完成类型的转换 beanWrapper.convertIfNecessary("Tom", requiredType, methodParam)

springmvc自定义类型转换

  • 如果springmvc遇到了其内部不能进行转换的request parameter呢?那么就需要注册PropertyEditor
  • 举例来说,java.util.Date 不知道 13/09/2010 代表什么,
  • 所有要由我们程告诉spring(因为Date的格式有多种,所以spring不好来进行直接转换,需要我们自己定义格式来转换)
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
    public void setAsText(String value) {
        try {
            setValue(new SimpleDateFormat("dd/MM/yyyy").parse(value));
        } catch(ParseException e) {
            setValue(null);
        }
    }
 
/**
  * 这个方法似乎没什么用
  */
 
    public String getAsText() {
        return new SimpleDateFormat("dd/MM/yyyy").format((Date) getValue());
    }        
 
});
  • 当调用convertIfNecessary方法时,spring会寻找所有注册了的PropertyEditor来处理数据的绑定。
  • 为了注册我们的PropertyEditor,在spring3.0中,使用
@InitBinder
public void binder(WebDataBinder binder) {
    // as shown above 上面的代码
} 
  • controller有两种写法
    • 写法二是原始写法,直接new PropertyEditorSupport类,
    • 写法一使用spring提供的CustomDateEditor实现类,其实际上继承了PropertyEditorSupport类
@Controller
@RequestMapping(value = "/user")
public class UserAction {
    //自定义类型转换器 如果springmvc遇到不能进行转换的Date类型
	//通过名称来对应调用这个方法
 
    //写法1 使用spring提供的CustomDateEditor实现类,其实际上继承了PropertyEditorSupport类
    @InitBinder
    public void initBinder(ServletRequestDataBinder binder){
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
                true));
    }
 
    //写法2 直接使用PropertyEditorSupport类
    @InitBinder
    public void binder(WebDataBinder binder){
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport(){
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                try {
                    setValue(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(text));
                } catch (ParseException e) {
                    setValue(null);
                }
            }
        });
    }
 
    @RequestMapping("/register")
    public String register(Model model, User user){
        System.out.println(user);
        Date date = user.getHiredate();
        System.out.println(date.toLocaleString());
        model.addAttribute("message", "员工注册成功");
        return "success";
    }
}