# 数据校验
# 概述
在 Web 应用程序中,为了防止客户端传来的数据引发程序异常,常常需要对数据进行验证。
数据验证分为:
- 客户端验证
- 客户端验证主要通过 JavaScript 脚本进行。
- 服务端验证
- 服务端验证主要通过 Java 代码进行验证。
为了保证数据的安全性,客户端和服务端验证都是必须的。
Spring MVC 提供了强大的数据校验功能,其中有两种方法可以验证输入:
- 利用 Spring 自带的 Validation 校验框架(早于 JSR 303,不建议使用)
- 利用 JSR 303(Java 校验规范)实现校验功能
JSR 只是一套规范,其具体的实现中 Hibernate Validator 是最常见的实现,它即实现了 JSR 303 的要求,又实现了更新的 JSR 349 的要求)。
WARNING
由于版本原因,使用 hibernate-validator 6.x 版本
和 使用 tomcat 7 插件
只能二选一。
Spring MVC 对 JSR 提供了良好的支持,如果,Spring MVC 的配置文件中配置了 <mvc:annotation-driven />
,那么就不再需要其它任何配置了。
以下 所有 注解都有 message
属性用以在验证不通过是显示提示信息。
# JSR 303 的注解
注解 | 说明 |
---|---|
@Null | 被注解的元素必须为 null |
@NotNull | 被注解的元素必须不为 null |
@AssertTrue | 被注解的元素必须为 true |
@AssertFalse | 被注解的元素必须为 false |
@Min | 被注解的元素必须是一个数字,其值必须小于指定值。 |
@Max | 被注解的元素必须是一个数字,其值必须大于指定值。 |
@DecimalMin | 被注解的元素必须是一个数字,其值必须小于指定值。 |
@DecimalMax | 被注解的元素必须是一个数字,其值必须大于指定值。 |
@Size(min, max) | 被注解的数组和集合型元素的长度是必须给定的范围之内 |
@Digits(integer, fraction) | 要求字符串必须是数字型字符串,且整数部分有 interger 位, 小数部分有 fraction 位。 |
@Past | 要求必须是一个过去日期。用于 Date 和 Calendar |
@Future | 要求必须是一个未来日期。用于 Date 和 Calendar |
@Pattern(regexp, flag) | 要求字符串内容必须符合正则表达式的规则 |
@Valid | 要求递归检查数组和容器中关联对象。 |
所有的这些注解都有 message 属性,用于设置错误提示信息(如果没有设置,则会有默认的错误提示信息)。
# Hibernate Validator 的扩展注解
Hibernate Validator 实现了 JSR 303,它除了支持所有标准的校验注解外,还支持一些『额外』的注解:
注解 | 说明 |
---|---|
@NotBlank | 要求字符串必须不为 NULL,且执行 trim() 后必须为非空字符串 |
@Email | 要求字符串内容必须符合邮箱格式。但是 null 会放过 |
@Length(min, max) | 要求字符串的长度必须在指定范围内 |
@NotEmpty | 备注解的字符串必须为非空 |
@Range(min, max) | 检查数字是否介于 min 和 max 之间 |
# 使用 JSR 303
注意
使用验证框架时,请求处理方法的参数对象必须用 @Valid
注解修饰,并且处理方法要多出一个 BindingResult
参数对象。
@RequestMapping("...")
public ModelAndView demo(@Valid ..., BindingResult result) {
...;
}
BindingResult 参数对象中包含了验证结果,及其相关信息。
if (result.hasErrors()) {
List<FieldError> list = result.getFieldErrors();
for (FieldError error : list) {
System.out.println(error.getField() + ", " + error.getDefaultMessage());
}
}
更优雅的改进方案:结合全局异常处理,当 result.hasErrors() == true
时,在 Controller 中直接抛出异常,由 Controller 的异常处理类来解析 BindingResult 中的异常信息,并返回对应的错误信息给客户端。