springmvc参数收集与类型转换源码解析

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

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

首先用代码来模拟mock一个request请求

/**
  * Bundled Mock request 模拟一个请求,把参数放到request中
  */
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter("name", "Tom");
request.addParameter("age", "25");

/**
  * Spring create a new command object before processing the request
  *
  * By calling <COMMAND_CLASS>.class.newInstance(); 
  */
Person person = new Person();

接下来ServletRequestDataBinder出场了,由它来绑定提交的数据

/**
  * And Then with a ServletRequestDataBinder, it bind the submitted values  ServletRequestDataBinder出场了,由它来绑定提交的数据
  * 
  * It makes use of Java reflection To bind its values
  */
ServletRequestDataBinder binder = ServletRequestDataBinder(person);
binder.bind(request);

在程序内部,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 上面的代码
}

举例

比如说写了一个emp.jsp页面,需要对hiredate进行转换

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>springmvc收集参数</title>
</head>
<body>
    <form action="${requestScope.request.contextPath}/demo01/user/register" method="post">
        <table border="2" align="center">
            <caption><h2>用户注册</h2></caption>
            <tr>
                <th>姓名</th>
                <td><input type="text" name="username"/></td>
            </tr>
            <tr>
                <th>月薪</th>
                <td><input type="text" name="salary" value="7000"/></td>
            </tr>
            <tr>
                <th>入职时间</th>
                <td><input type="text" name="hiredate" value="2015-5-11 12:12:12"/></td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <input type="submit" value="注册" style="width:111px"/>
                </td>
            </tr>
        </table>
    </form>    
</body>
</html>

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";
    }
}
参考: https://stackoverflow.com/questions/3705282/spring-mvc-binding-a-date-field
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值