Springmvc支持将参数封装到对象中,步骤如下所示:
和大部分框架一样,Springmvc不支持StringàDate类型的转换,这时就需要自己注册一个“用户数据编辑器”CustomDateEditor,这个注册的步骤应该在initBinder(request,binder)方法中完成,如下所示:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
CustomDateEditor dateEditor = new CustomDateEditor(sdf, true);
binder.registerCustomEditor(Date.class, dateEditor);
PhoneDataEditor phoneDataEditor = new PhoneDataEditor();
这样就可以将符合格式字符串转换成Date对象。
如果我们想定义自己的“用户编辑器”,应该继承PropertyEditorSupport这个类,并覆写public String getAsText()和public void setAsText(String text)方法,事例代码如下:
编辑器
public class PhoneDataEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
// TODO Auto-generated method stub
PhoneNumber number = (PhoneNumber)getValue();
return number == null?"":number.getAreaCode()+"--"+number.getPn();
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
// TODO Auto-generated method stub
Pattern p = Pattern.compile("^(\\d{3,4})-(\\d{7,8})$");
if(text==null||!StringUtils.hasLength(text)){
setValue(null);
}
Matcher matcher = p.matcher(text);
if(matcher.matches()){
PhoneNumber number = new PhoneNumber();
number.setAreaCode(matcher.group(1));
number.setPn(matcher.group(2));
setValue(number);
}else{
throw new IllegalArgumentException("时间格式错误,无法进行转换");
}
}
}
Domain对象(1)
public class DataTest {
private String type;
private PhoneNumber phone;
private Date birthday;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public PhoneNumber getPhone() {
return phone;
}
public void setPhone(PhoneNumber phone) {
this.phone = phone;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
Domain对象(2)
public class PhoneNumber {
private String areaCode;
private String pn;
public String getAreaCode() {
return areaCode;
}
public void setAreaCode(String areaCode) {
this.areaCode = areaCode;
}
public String getPn() {
return pn;
}
public void setPn(String pn) {
this.pn = pn;
}
}
Controller
public class DataTransferController extends AbstractCommandController{
public DataTransferController(){
this.setCommandClass(DataTest.class);
this.setCommandName("data");
}
@Override
protected ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
// TODO Auto-generated method stub
System.out.println(command);
return new ModelAndView("index").addObject("data1", command);
}
/* (non-Javadoc)
* @see org.springframework.web.servlet.mvc.BaseCommandController#initBinder(javax.servlet.http.HttpServletRequest, org.springframework.web.bind.ServletRequestDataBinder)
*/
@Override
protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) throws Exception {
// TODO Auto-generated method stub
super.initBinder(request, binder);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
CustomDateEditor dateEditor = new CustomDateEditor(sdf, true);
binder.registerCustomEditor(Date.class, dateEditor);
PhoneDataEditor phoneDataEditor = new PhoneDataEditor();
binder.registerCustomEditor(PhoneNumber.class, phoneDataEditor);
}
}
从上图中可以看到绑定命令对象执行方法的顺序,其实是在第三部binder.bind(request)方法中完成数据的绑定,因此在controller中可以覆写initBinder()方法,将自定义的“编辑器”注册,从而完成数据的转换。测试路径(http://127.0.0.1:8080/springmvctest/dataBind?type=howareyou&birthday=2012-3-18%2016:48:48&phone=010-12345678)
通过跟踪源代码可以看到,在BeanWrapperImpl的setPropertyValue()方法中绑定命令对象, setPropertyValue方法中有一个convertIfNecessary()方法,convertIfNecessary方法又调用了TypeConverterDelegate的convertIfNecessary()方法,这个方法中真正干活的是doConvertValue()方法,doConvertValue方法又调用了另外一个成员方法doConvertTextValue(),源代码如下:
protected Object doConvertTextValue(Object oldValue, String newTextValue, PropertyEditor editor) {
try {
editor.setValue(oldValue);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", ex);
}
// Swallow and proceed.
}
editor.setAsText(newTextValue);
return editor.getValue();
}
很容易发现,调用了editor的setAsText()方法,为什么要调用getAsText()方法,通过查看PropertyEditorSupport很容易理解