我们知道,对于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