5.4.2 校验表单
如果用户在提交表单的时候,username 或 password 文本域为空的话,那么将会导致在新建 Spitter 对象中,username 或 password 是空的 String。至少这是一种怪异的行为。如果这种现象不处理的话,这将会出现安全问题,因为不管是谁只要提交一个空的表单就能登录应用。
同时,我们还应该阻止用户提交空的 firstName 和 / 或 lastName,使应用仅在一定程度上保持匿名性。有个好的办法就是限制这些输入域值的长度,保持它们的值在一个合理的长度范围,避免这些输入域的误用。
有种处理校验的方式非常初级,那就是在 processRegistration() 方法中添加代码来检查值的合法性,如果值不合法的话,就将注册表单重新显示给用户。这是一个很简短的方法,因此,添加一些额外的 if 语句也不是什么大问题,对吧?
与其让校验逻辑弄乱我们的处理器方法,还不如使用 Spring 对 Java 校验 API(Java Validation API,又称 JSR-303)的支持。从 Spring 3.0 开 始,在 Spring MVC 中提供了对 Java 校验 API 的支持。在 Spring MVC 中要使用 Java 校验 API 的话,并不需要什么额外的配置。只要保证在类路径下包含这个 Java API 的实现即可,比如 Hibernate Validator。
Java 校验 API 定义了多个注解,这些注解可以放到属性上,从而限制这些属性的值。所有的注解都位于 javax.validation.constraints 包中。表 5.1 列出了这些校验注解。
注解
描述
@AssertFalse
所注解的元素必须是 Boolean 类型,并且值为 false
@AssertTrue
所注解的元素必须是 Boolean 类型,并且值为 true
@DecimalMax
所注解的元素必须是数字,并且它的值要小于或等于给定的 BigDecimalString 值
@DecimalMin
所注解的元素必须是数字,并且它的值要大于或等于给定的 BigDecimalString 值
@Digits
所注解的元素必须是数字,并且它的值必须有指定的位数
@Future
所注解的元素的值必须是一个将来的日期
@Max
所注解的元素必须是数字,并且它的值要小于或等于给定的值
@Min
所注解的元素必须是数字,并且它的值要大于或等于给定的值
@NotNull
所注解元素的值必须不能为 null
@Null
所注解元素的值必须为 null
@Past
所注解的元素的值必须是一个已过去的日期
@Pattern
所注解的元素的值必须匹配给定的正则表达式
@Size
所注解的元素的值必须是 String、集合或数组,并且它的长度要符合给定的范围
除了表 5.1中的注解,Java 校验 API 的实现可能还会提供额外的校验注解。同时,也可以定义自己的限制条件。但就我们来讲,将会关注于上表中的两个核心限制条件。
请考虑要添加到 Spitter 域上的限制条件,似乎需要使用 @NotNull 和 @Size 注解。我们所要做的事情就是将这些注解添加到 Spitter 的属性上。如下的程序清单展现了 Spitter 类,它的属性已经添加了校验注解。
1
package spittr;
2
3
import javax.validation.constraints.NotNull;
4
import javax.validation.constraints.Size;
5
6
import org.apache.commons.lang3.builder.EqualsBuilder;
7
import org.apache.commons.lang3.builder.HashCodeBuilder;
8
9
public class Spitter {
10
11
private Long id;
12
13
@NotNull
14
@Size(min=5, max=16)
15
private String username;
16
17
@NotNull
18
@Size(min=5, max=25)
19
private String password;
20
21
@NotNull
22
@Size(min=2, max=30)
23
private String firstName;
24
25
@NotNull
26
@Size(min=2, max=30)
27
private String lastName;
28
29
...
30
}
Copied!
现在,Spitter 的所有属性都添加了 @NotNull 注解,以确保它们的值不为 null。类似地,属性上也添加了 @Size 注解以限制它们的长度在最大值和最小值之间。对 Spittr 应用来说,这意味着用户必须要填完注册表单,并且值的长度要在给定的范围内。
我们已经为 Spitter 添加了校验注解,接下来需要修改 processRegistration() 方法来应用校验功能。启用校验功能的 processRegistration() 如下所示:
程序清单 5.19 processRegistration():确保所提交的数据是合法的
1
@RequestMapping(value="/register", method=POST)
2
public String processRegistration(
3
@Valid Spitter spitter,
4
Errors errors) {
5
if (errors.hasErrors()) {
6
return "registerForm";
7
}
8
9
spitterRepository.save(spitter);
10
return "redirect:/spitter/" + spitter.getUsername();
11
}
Copied!
与程序清单5.17 中最初的 processRegistration() 方法相比,这里有了很大的变化。Spitter 参数添加了 @Valid 注解,这会告知 Spring,需要确保这个对象满足校验限制。
在 Spitter 属性上添加校验限制并不能阻止表单提交。即便用户没有填写某个域或者某个域所给定的值超出了最大长度,processRegistration() 方法依然会被调用。这样,我们就需要处理校验的错误,就像在 processRegistration() 方法中所看到的那样。
如果有校验出现错误的话,那么这些错误可以通过 Errors 对象进行访问,现在这个对象已作为 processRegistration() 方法的参数。(很重要一点需要注意,Errors 参数要紧跟在带有 @Valid 注解的参数后面,@Valid 注解所标注的就是要检验的参数。)processRegistration() 方法所做的第一件事就是调用Errors.hasErrors() 来检查是否有错误。
如果有错误的话,Errors.hasErrors() 将会返回到registerForm,也就是注册表单的视图。这能够让用户的浏览器重新回到注册表单页面,所以他们能够修正错误,然后重新尝试提交。现在,会显示空的表单,但是在下一章中,我们将在表单中显示最初提交的值并将校验错误反馈给用户。
如果没有错误的话,Spitter 对象将会通过 Repository 进行保存,控制器会像之前那样重定向到基本信息页面。
Last modified 2yr ago
Copy link