目录
数据绑定
在执行程序时SpringMVC会根据客户端发送的请求参数的不同,将请求消息中的信息以特定的方式转换并绑定到Controller的方法参数中。这种前后端进行连接的过程就是数据绑定。
SpringMVC进行数据绑定的运行机制如下图所示。
数据绑定信息处理过程的步骤如下:
- SpringMVC框架将ServletRequest对象传递给DataBinder。
- 将处理方法入参对象实例传递给DataBinder。
- DataBinder调用装配在SpringMVC上下文中的ConversionService组件进行数据类型转换、数据格式化等工作,并将ServletRequest对象中的消息填充到参数对象中。
- 调用Validator组件对已绑定了的请求消息数据的参数对象进行数据合法性校验。
- 将生成的数据绑定结果BIndingResult对象中的内容赋给处理方法的相应参数。
数据类型转换
使用ConversionService进行类型转换
1.配置ConversionServiceFactoryBean
在ConversionServiceFactoryBean中可以内置很多类型转换器使用它们可以完成大多数的Java类型转换工作,可以通过在ConversionServiceFactoryBean的converters属性注册自定义的类型转换器,配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"
xmlns:p="http://www.springframework.org/schema/p">
<!-- 配置包扫描,扫描controller包中的注解 -->
<context:component-scan base-package="controller"/>
<!-- 驱动 -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 配置视图解析器,将控制器方法返回的逻辑视图解析为物理视图 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 我这里的jsp实际位置为 WebRoot/jsp/xxx.jsp -->
<property name="prefix" value="jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 类型转换第一步,配置ConversionServiceFactoryBean -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="converter.StringToDateConverter" p:datePattern="yyyy-MM-dd">
<!-- <property name="datePattern">yyyy-MM-dd</property> -->
</bean>
</list>
</property>
</bean>
</beans>
小提示
需要注意的是,这里我们使用了p命名空间来引入属性,需要提前声明才可以使用,在beans标签下添加下方的代码即可。
xmlns:p="http://www.springframework.org/schema/p"
p命名空间是property的首字母,它可以将property通过标签属性的方式注入bean,简化了代码开发。
2.新建StringToDateConverter类,实现Converter接口
细心的同学可能已经发现,我们在配置文件中配置了一个名为“converter.StringToDateConve”的bean,下面我们需要创建并编写这个类。
在src下创建converter包,在包内创建StringToDateConve并实现Converter接口,具体代码如下:
package converter;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
public class StringToDateConverter implements Converter<String, Date>{
//设置日期格式,有默认值
private String datePattern;
public void setDatePattern(String datePattern) {
this.datePattern = datePattern;
}
//执行转换
@Override
public Date convert(String date) {
try {
//日期格式化
SimpleDateFormat sdf = new SimpleDateFormat(this.datePattern);
//返回转换结果
return sdf.parse(date);
} catch (Exception e) {
//异常处理
e.printStackTrace();
System.out.println("转换失败!");
return null;
}
}
}
3.编写实体类与控制类
这里我们在entity包中定义一个User类用作测试,其拥有name、birthday两个属性,生成Getter和Setter,代码较简单,不多赘述。
接着在controller包中创建一个controller类,用于接受请求并处理jsp传入的数据。代码如下:
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import entity.User;
@Controller
public class LoginController {
@RequestMapping("register")
public String login(Model m,@ModelAttribute User user) {
System.out.println(user.getBirthday());
m.addAttribute("user", user);
return "success";
}
}
4.编写jsp
接着创建两个jsp,一个用来提交数据,一个用来展示数据。
index.jsp(部分):
<form action="register" method="post">
用户名:<input type="text" id="name" name="name"><br>
生 日:<input type="text" id="birthday" name="birthday"><br>
<input type="submit" value="注册">
</form>
success.jsp(部分):
<body>
用户名:${user.name }<br>
生日:${user.birthday }
</body>
5.测试运行
将项目保存并部署到Tomcat,在浏览器中访问,输入生日并点击注册按钮。
可以看到格式转换成功了。
但是,上面的方式太麻烦了,Spring还贴心的为我们准备了更简单的做法。
使用@InitBinder注解进行类型转
在本项目的基础上,在controller中添加initBinder方法,用@InitBinder注解进行标识,同时编写一个新的方法映射新的请求。
@RequestMapping("binderRegister")
public String binderLogin(Model m,@ModelAttribute User user) {
System.out.println(user.getBirthday());
m.addAttribute("user", user);
return "success";
}
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
}
最后在index.jsp中再添加一个表单,action为binderRegister。
binder
<form action="binderRegister" method="post">
用户名:<input type="text" id="name" name="name"><br>
生 日:<input type="text" id="birthday" name="birthday"><br>
<input type="submit" value="注册">
</form>
测试运行
大功告成!
总结
- @InitBinder注解标识的方法可以对WebDataBinder对象进行初始化,用于完成从表单文本域到实体类属性的绑定。
- @InitBinder注解标识的方法不能有返回值。
- @InitBinder注解标识的方法参数为WebDataBinder,是DataBinder的子类,DataBinder是数据绑定的核心(见文章开头图)
- 对于同一个类型的对象来说,如果同时在ConversionService中装配了自定义的转换器,同时还在控制器中通过@InitBinder注解装配了自定义的编辑器,SpringMVC将优先使用@InitBinder注解装配的编辑器,再使用ConversionService中装配的转换器。
- 每次请求都会先调用@InitBinder注解标识的方法,再执行处理请求的方法。