前面几章我们已经实现了页面的输入功能,但还缺少对用户录入项的校验,以防止用户漏输或者输入错误。本章来实现表单校验功能。
在我们之前的配料表单中,对用户的输入并没有控制。如果用户一个配料都没有选,或者没有给他的配料表命名,我们的页面都不会报错。这在实际的应用系统中是不能发生的。因此,在这一章,我们需要给表单增加输入校验功能。
Spring 支持Java的Bean校验API(Bean Validation API,也就是JSR-303)。它能够帮助我们更容易的声明校验规则,而不用在代码中显式的声明校验逻辑。
要在Spirng MVC中应用校验,需要做到下面三步:
- 在要增加校验的类上面声明校验规则,例如在Taco类;
- 在控制器中方法声明要进行的校验;
- 修改表单视图以展现校验错误。
一、声明校验规则
在Taco类里面,我们要确保name属性不为空,同时配料至少要包含一项。这就要使用@NotNull 和 @Size注解来解决我们的问题,代码如下:
@Data
public class Taco {
@NotNull
@Size(min=5, message="Name must be at least 5 characters long")
private String name;
@Size(min=1, message="You must choose at least 1 ingredient")
private List<String> ingredients;
}
注解比较简单,给出了每个字段在大小方面的规则。
我们继续对“Order”订单类增加规则校验。代码如下。
@Data
public class Order {
@NotBlank(message="名称不能为空")
private String name;
@NotBlank(message="街道名称不能为空")
private String street;
@NotBlank(message="街道名称不能为空")
private String city;
@NotBlank(message="街道名称不能为空")
private String state;
@NotBlank(message="街道名称不能为空")
private String zip;
@CreditCardNumber()
private String ccNumber;
@Pattern(regexp = "^(0[1-9]|1[0-2])([\\/])([1-9][0-9])$",
message="Must be formatted MM/YY")
private String ccExpiration;
@Digits(integer=3, fraction = 0,message = "CVV编号不合法")
private String ccCVV;
}
Order类的校验控制大部分是非空校验,使用了@NotBlank注解。其他几个比较特殊的注解是:
- @CreditCardNumber注解。这个注解声明该属性的值必须是合法的信用卡号,防止用户录错信用卡。
- @Pattern注解。这个注解采用了正则表达式,这里确保了用户输入的信用卡到期日的格式是“MM/YY”格式。
- @Digits注解。这个注解确保它的值包含3位数字。
所有注解都包含了一个message属性,定义了当输入的信息不满足声明的校验规则的时候,展现给用户什么信息。
二、在控制器内执行校验
接下来我们要修改控制器,让表单在POST提交时,对应的控制器方法能够执行相应的校验。
DesignTacoController类的processDesign()方法的代码修改如下:
@PostMapping
public String processDesign(@Valid Taco design, Errors errors){
if(errors.hasErrors()){
return "design";
}
log.info("Processing design: " + design);
return "redirect:/orders/current";
}
首先,为这个方法的Taco输入参数增加一个@Valid注解。这个注解会通知Spring MVC要对提交的Taco对象进行校验,这个校验发生在绑定表单数据之后,调用processDesign()方法之前。如果存在校验错误,则错误信息会传递到errors对象中。程序的前几行会校验errors对象是否存在错误,如果存在,则跳转到“design”视图中去。
对OrderController类的processOrder方法也做类似的修改,代码如下:
@PostMapping
public String ProcessOrder(@Valid Order order, Errors errors){
if(errors.hasErrors()){
return "orderForm";
}
log.info("order submitted:" + order);
return "redirect:/";
}
作用和原理与之前介绍的类似。
三、增加视图校验
Thymeleaf模板提供了能够访问Errors对象的方法,就是使用fields及th:errors标签,该元素会将对错误的引用带到订单的表单模板上。
表单校验的关键代码是这样的:
<label for="name">Name: </label>
<input type="text" th:field="*{name}"/>
<!-- end::allButValidation[] -->
<span class="validationError"
th:if="${#fields.hasErrors('name')}"
th:errors="*{name}">Name Error</span>
<!-- tag::allButValidation[] -->
<br/>
这里使用th:if属性来判断是否需要显示这个报错提示,显然,当判断是hasErrors时需要显示报错信息。
th:errors则判断,当name这个变量存在错误的时候,将显示“Name Error”这个报错信息。
最终显示的报错提示如下,我这里用了汉语的报错信息。
页面的报错信息.png
具体的页面代码,大家可以在官网的代码库中获取。
四、总结
目前为止,我们已经完成了页面的get、post请求,并为页面增加了输入校验规则。SpringMVC中,校验规则的增加是比较方便的,只要分别在要需要校验的类、控制器以及页面中增加相应的内容即可。
后面我们将继续修改这个例子,在其中增加数据库支持。
网友评论