08.SpringMVC_数据绑定的流程
1.当我们提交表单,将表单中的数据绑定的方法的入参的对象中时,会涉及到数据绑定的流程,数据绑定的流程分为:数据类型转换、数据格式化、数据校验
- 数据类型转换
- SpringMVC默认为我们装配了以下类型转换器:
- 如果SpringMVC默认的类型转换器不能满足我们的需求,我们可以自定义类型转换器,如:将一个字符串转换为Employee对象
- 创建一个类实现Converter<S,T>接口
public
class MyConverter implements Converter<String, Employee> {
// [email protected]-1-101 这种格式的写法转换
@Override
public Employee convert(String
arg0) {
Employee employee =
null;
if(arg0 !=
null){
String[] split =
arg0.split("-");
if(split !=
null &&
split.length == 4){
//获取姓名
String lastName =
split[0];
//获取邮箱
String email =
split[1];
//获取性别
int
gender = Integer.parseInt(split[2]);
//获取部门的id
int
deptId = Integer.parseInt(split[3]);
//创建Employee对象
employee =
new Employee();
employee.setLastName(lastName);
employee.setEmail(email);
employee.setGender(gender);
employee.setDepartment(new DepartmentDao().getDepartment(deptId));
}
}
return
employee;
}
}
- 在SpringMVC配置文件中配置自定义的类型转换器
<!-- 配置类型转换器 -->
<bean
id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property
name="converters">
<set>
<bean
class="com.atguigu.springmvc.converter.MyConverter"></bean>
</set>
</property>
</bean>
<mvc:annotation-driven
conversion-service="conversionService"></mvc:annotation-driven>
这个必须写在<mvc:annotation-driven></mvc:annotation-driven>之前才行
// 测试自定义转换器
@RequestMapping(value =
"/testMyConverter", method = RequestMethod.POST)
public String testMyConverter(@RequestParam("employee") Employee
employee) {
// 保存该员工
System.out.println(employee);
employeeDao.save(employee);
return
"redirect:/getEmployees";
- 备注:
在Handler中通过 @InitBinder这个标签在数据绑定的过程不允许给某一个属性赋值
@InitBinder
public void initGender(WebDataBinder dataBinder){
//数据绑定的过程不允许给性别赋值
dataBinder.setDisallowedFields("gender");
}
- @InitBinder方法不能有返回值,它必须声明为void。
- @InitBinder方法的参数通常是 WebDataBinder
- 备注:
<mvc:annotation-driven/>配置在什么时候必须配置?
- 直接配置响应的页面:无需经过控制器来执行结果 ;但会导致其他请求路径失效,需要配置mvc:annotation-driven标签<mvc:view-controller path="/success" view-name="success"/>
- 通过jQuery执行delete请求时,找不到静态资源,需要配置mvc:annotation-driven标签
- 配置类型转换器服务时,需要指定转换器服务引用<mvc:annotation-driven conversion-service=“conversionService”/> 会将自定义的ConversionService 注册到 Spring MVC 的上下文中
- 数据验证,也需要配置
3.数据的格式化
- 我们可以通过@DateTimeFormat和@NumberFormat注解对应日期和数据进行格式化,只需要在要格式化的类的属性上添加以上注解即可
@DateTimeFormat(pattern =
"yyyy-MM-dd")
private Date
birthday;
@NumberFormat(pattern="#,###,###.##")
private
double salary;
- 要使@DateTimeFormat和@NumberFormat注解起作用,必须配置<mvc:annotation-driven></mvc:annotation-driven>
<mvc:annotation-driven></mvc:annotation-driven>
配置,配置时不能指定conversion-service属性,否则,依然报错400。要把<mvc:annotation-driven conversion-service="conversionService"/>注掉才行
备注:
FormattingConversionService 实现类,既具有类型转换的功能,又具有格式化的功能
- <mvc:annotation-driven/> 默认创建的 ConversionService 实例即为
DefaultFormattingConversionService
4.数据校验
- 我们可以通过Hibernate Validator进行数据校验,使用它需要到导入以下jar包
classmate-0.8.0.jar
hibernate-validator-5.0.0.CR2.jar
hibernate-validator-annotation-processor-5.0.0.CR2.jar
jboss-logging-3.1.1.GA.jar
validation-api-1.1.0.CR1.jar
- 然后在要校验的属性上添加对应的注解
@NotEmpty
private String
lastName;
@Email
private String
email;
@Past
private Date
birthday;
- 在要校验的属性对应的对象的前面添加@Valid注解,同时紧挨着该对象传入BindingResult类型的入参,通过它获取异常信息
// 添加新员工
@RequestMapping(value =
"/emp", method = RequestMethod.POST)
public String addEmployee(@Valid Employee
employee , BindingResult
result) {
//BindingResult结果集对象必须紧挨着被校验的employee对象,中间不能有其他参数
// System.out.println(employee);
int
errorCount = result.getErrorCount();
if(errorCount > 0){
//证明有错误信息
List<FieldError> fieldErrors =
result.getFieldErrors();
for (FieldError
fieldError : fieldErrors) {
//获取出现异常的属性
String field =
fieldError.getField();
//获取异常信息
String message =
fieldError.getDefaultMessage();
System.out.println(field+":"+message);
}
//转发到输入用户信息的页面
return
"input";
}
// 保存用户
employeeDao.save(employee);
return
"redirect:/emps";
}
- 要想当校验的注解起作用,必须配置<mvc:annotation-driven></mvc:annotation-driven>
<mvc:annotation-driven></mvc:annotation-driven>
- 通过<form:errors></form:errors>表单在前端页面显示错误信息
<!-- SpringMVC提供的表单默认表单中的数据是必须要回显的,默认情况下,SpringMVC会以command 作为key从request域中
查询模型数据,然后回显,找不到则会抛出异常。我们可以通过form表单的modelAttribute属性来指定在request域中放的模型数据的key
-->
<form:form
modelAttribute="employee">
<!-- 如果path的值为通配符*,将显示所有的错误信息,如果要显示对应的错误信息,将该值设置为属性名即可-->
<%-- <form:errors path="*"></form:errors>
--%>
<!-- path属性就相当于input中的name属性 -->
<!-- 当员工的id为null,即在添加新员工时再显示姓名 -->
<c:if
test="${empty requestScope.employee.id }">
姓名:<form:input
path="lastName"/><form:errors
path="lastName"></form:errors><br>
</c:if>
<!-- 对应更新来说,需要将POST请求转换为PUT请求,所以需要传一个请求参数_method -->
<c:if
test="${!empty requestScope.employee.id }">
<form:hidden
path="id"/>
<input
type="hidden"
name="_method"
value="put">
</c:if>
邮箱:<form:input
path="email"/><form:errors
path="email"></form:errors><br>
性别:<form:radiobutton
path="gender"
value="1"
label="男"/>
<form:radiobutton
path="gender"
value="0"
label="女"/><br>
部门:<form:select
path="department.id"
items="${requestScope.depts }"
itemValue="id"
itemLabel="departmentName"></form:select>
<br>
生日:<form:input
path="birthday"/><form:errors
path="birthday"></form:errors><br>
期望薪资:<form:input
path="salary"/><br>
<input
type="submit">
</form:form>
- 国际化错误信息
- 在SpringMVC的配置文件中配置国际化资源文件
<!-- 配置国际化资源文件 -->
<bean
id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property
name="basename"
value="i18n"></property>
</bean>
- 国际化资源文件(i18n_zh_CN.properties)
NotEmpty.employee.lastName=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
Email.employee.email=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E
Past.employee.birthday=\u4EB2\u7231\u7684\uFF0C\u4F60\u51FA\u751F\u7684\u65F6\u95F4\u8FD8\u6CA1\u5230\uFF0C\u5728\u4F60\u5988\u5988\u809A\u5B50\u91CC\u518D\u5446\u4E9B\u65F6\u65E5\u5427\uFF01\uFF01\uFF01