数据校验
一、使用 Hibernate Validator 验证器
1.导包:
- classmate-1.3.4.jar
- hibernate-validator-6.0.9.Final.jar
- javax.el-3.0.1-b09.jar
- jboss-logging-3.3.2.Final.jar
- validation-api-2.0.1.Final.jar
2.配置 mvc:annotation-driven
<mvc:annotation-driven></mvc:annotation-driven>
- 会自动注册 RequestMappingHandlerMapping、RequestMappingHandlerAdapter 与ExceptionHandlerExceptionResolver 三个bean。
- 还将提供以下支持:
- 支持使用 ConversionService 实例对表单参数进行类型转换
- 支持使用 @NumberFormat annotation、@DateTimeFormat注解完成数据类型的格式化
- 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
- 支持使用 @RequestBody 和 @ResponseBody 注解
二、JSR 303
1.JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中 .
2.JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max等标准的注解指定校验规则,并通过标准的验证接口对 Bean进行验证

3.Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解

示例代码:
Employee:
import java.util.Date;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Past;
import org.hibernate.validator.constraints.Range;
import org.springframework.format.annotation.DateTimeFormat;
public class Employee {
private Integer id;
@NotBlank(message="姓名不能为空")
private String name;
@Range(min=1,max=120,message="年龄在 1-120 之间")
private Integer age;
@Range(min=0,max=1,message="请输入 0 或 1")
private Integer gender;
private String address;
@Past(message="时间不合法")
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
public Employee() {
super();
}
public Employee(Integer id, String name, Integer age, Integer gender, String address) {
super();
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + ", Address=" + address
+ ", birth=" + birth + "]";
}
}
三、Spring MVC 数据校验
- Spring 4.0 拥有自己独立的数据校验框架,同时支持 JSR
303 标准的校验框架。 - Spring 在进行数据绑定时,可同时调用校验框架完成数据校
验工作。在 Spring MVC 中,可直接通过注解驱动的方式
进行数据校验 - Spring 的 LocalValidatorFactroyBean 既实现了 Spring 的
Validator 接口,也实现了 JSR 303 的 Validator 接口。只要
在 Spring 容器中定义了一个 LocalValidatorFactoryBean,即可将其注入到需要数据校
验的 Bean 中。 - Spring 本身并没有提供 JSR303 的实现,所以必须将JSR303 的实现者的 jar 包放到类路径下。
- 会默认装配好一个LocalValidatorFactoryBean,通过在处理方法的入参上标注 @valid 注解即可让 Spring MVC 在完成数据绑定后执行数据校验的工作
- 在已经标注了 JSR303 注解的表单/命令对象前标注一个@Valid,Spring MVC 框架在将请求参数绑定到该入参对象后,就会调用校验框架根据注解声明的校验规则实施校验
- Spring MVC 是通过对处理方法签名的规约来保存校验结果的:前一个表单/命令对象的校验结果保存到随后的入参中,这个保存校验结果的入参必须是 BindingResult 或 Errors 类型,这两个类都位于 org.springframework.validation 包中。
- 需校验的 Bean 对象和其绑定结果对象或错误对象是成对出现的,它们之间不允许声明其他的入参.
- Errors 接口提供了获取错误信息的方法,如 getErrorCount() 或 getFieldErrors(String field)
- BindingResult 扩展了 Errors 接口
在目标方法中获取结果:
- 在表单/命令对象类的属性中标注校验注解,在处理方法对应的入参前添加 @Valid,Spring MVC 就会实施校验并将校验结果保存在被校验入参对象之后的 BindingResult 或Errors 入参中。
实例代码:
@RequestMapping(value="/addEmployee",method=RequestMethod.POST)
public String addEmployee(@Valid Employee emp,BindingResult bindingResult,
Map<String,Object> map) {
employeeDAO.addEmployee(emp);
System.out.println(emp);
if(bindingResult.getErrorCount() > 0) {
for (FieldError error:bindingResult.getFieldErrors()) {
System.out.println(error.getField() + " : " + error.getDefaultMessage());
}
map.put("employee", emp);
return "addEmployee";
}
return "redirect:/getlist";
}
四、在页面上显示错误
- Spring MVC 除了会将表单/命令对象的校验结果保存到对应的 BindingResult 或 Errors 对象中外,还会将所有校验结果保存到 “隐含模型”
- 即使处理方法的签名中没有对应于表单/命令对象的结果入参,校验结果也会保存在 “隐含对象” 中。
- 隐含模型中的所有数据最终将通过 HttpServletRequest 的属性列表暴露给 JSP 视图对象,因此在 JSP 中可以获取错误信息
- 在 JSP 页面上可通过 显示错误消息
实例代码:
<body>
<form:form action="${pageContext.request.contextPath }/addEmployee" method="post" modelAttribute="employee">
<table>
<tr>
<td>Name:</td>
<td><form:input path="name" /></td>
<td style="color: red"><form:errors path="name" cssClass="error"></form:errors></td>
</tr>
<tr>
<td>Age:</td>
<td><form:input path="age" /></td>
<td><form:errors path="age" cssClass="error"></form:errors></td>
</tr>
<tr>
<td>Gender:</td>
<td><form:input path="gender" /></td>
<td><form:errors path="gender" cssClass="error"></form:errors></td>
</tr>
<tr>
<td>Birth:</td>
<td><form:input path="birth" /></td>
<td><form:errors path="birth" cssClass="error"></form:errors></td>
</tr>
<tr>
<td>Address:</td>
<td><form:input path="address" /></td>
<td><form:errors path="address" cssClass="error"></form:errors></td>
</tr>
<tr>
<td><input type="submit" value="Add"/></td>
</tr>
</table>
</form:form>
</body>