Spring MVC 表单验证

1. 前言

本节课讲解 Spring MVC 提供的验证框架,这个验证框架属于服务器端验证模式。通过本章节内容的学习,你将理解 JSR 概念,并能学到验证框架所提供的注解。

本章节重点是掌握 JSR 验证框架的使用;难点是理解其实现原理。

2. JSR

数据验证是对数据进行逻辑处理之前需要进行的一个很重要环节,如果不合要求的数据进入逻辑处理环节后,会导致程序的崩溃。

图片描述

WEB 应用程序中,验证用户提交的表单数据的合法性既可以在客户端实现,也可以在服务器端实现。

  • 客户端验证: 表单提交之前,通过客户端的 JS 脚本对表单中预提交的数据进行验证;
  • 服务器端验证: 数据提交到服务器后,由服务器端的的代码进行验证。

对于非敏感性的数据可以在客户端验证,如一些常规性的输入格式要求验证、类似于密码长度要多少、信息不能为空等。

服务器端相比较于客户端验证,会多出网络流量消耗。但是,对于一些敏感性的数据,比如身份证信息、银行卡信息…… 还是需要交给服务器的。

Spring MVC 提供的有验证框架,能够在绑定请求包中的数据时,按开发者提出的格式验证规则对数据进行验证。Spring MVC 验证框架的使用非常便利,只需要几个注解就能轻松解决问题。

使用之前,有几个概念先要交代清楚。

2.1 JSR 是什么

Tips: 不要看错了,是 JSR 不是 JSP。

JSR: Java 官方提供的数据合法性标准验证框架,它只是一个规范。现有多个版本:

  • Bean Validation 2.0 (JSR 380) ;
  • Bean Validation 1.1 (JSR 349);
  • Bean Validation 1.0 (JSR 303)。

准确的讲,Spring MVC 验证框架只是集成了 JSR 验证框架,并没有太多自己的具体实现。 JSR 提供了很多验证注解,一般放在要验证的 Bean 类型的属性前面。

  • @Null: 被注解的属性的值必须为空;
  • @NotNull: 被注解的属性的值可以不为空;
  • @Min(value): 注解数字类型的属性,其值大于等于指定的值;
  • @Max(value): 注解数字类型的属性,其值小于等于指定值;
  • @Size(max, min): 注解的属性值的大小必须是在给定的范围内(包括边界数字);
  • @Past: 注解日期类型属性,必须是一个过去的日期;
  • @Future: 注解日期类型属性,必须是一个将来的日期;
  • @Pattern(regexp): 使用正则表达式验证属性的值;
  • @Length(min,max): 属性值的长度在给定的范围之内(包括边界数字)。

Tips: 更多的验证注解大家可以查阅 JSR 官方文档。

了解了这些注解后,现在开始使用。

2.2 使用验证框架

2.2.1 验证前的准备

打开项目中的 pom.xml 文件,添加 validation-api 依赖包,大家需要注意一下,包名是以 javax 开头的。因为 Spring MVC 并没有实现 JSR 接口规范,这里选择 hibernate-validator

Tips: hibernate-validator 是 Hibernate 提供的 JSR 具体实现模块。

<dependency>
	<groupId>javax.validation</groupId>
	<artifactId>validation-api</artifactId>
	<version>2.0.1.Final</version>
</dependency>
<dependency>
	<groupId>org.hibernate.validator</groupId>
	<artifactId>hibernate-validator</artifactId>
	<version>6.1.0.Final</version>
</dependency>

打开 WebConfig 配置类,通知 Spring MVC 创建 LocalValidatorFactoryBean 对象。可以使用这个工厂对象创建具体的实现了 JSR 规范的验证器。

@Bean
public LocalValidatorFactoryBean validator() {
	LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
	localValidatorFactoryBean.setProviderClass(HibernateValidator.class);
	return localValidatorFactoryBean;
}

2.2.2 JSR 验证流程

先设定一个需求:添加老师信息。

  1. 构建一个 Teacher 类,并在 Teacher 类的相关属性上添加对应注解;
public class Teacher {
@NotNull(message = "姓名不能为空")
private String name;
   
@Min(value = 22,message = "年龄不能小于 22 岁")
private Integer age;

Tips: JSR 注解有一个 message 属性,用来保存错误提示信息。

  1. 编写 teacher.html 页面;
<form action="teacher/save" method="post">
   老师姓名:<input type="text" value="" name="name"/>
   <br/>
   老师年龄:<input type="text" value="" name="age"/>
   <br/>
   <input type="submit"  value="添加"  name="btnSave"/>
   <input type="reset"  value="重置"  name="btnReset"/>
</form>
  1. 编写响应控制器;
@Controller
@RequestMapping("/teacher")
public class TeacherAction {
   	@RequestMapping(value = "/save",method = RequestMethod.POST)
   	public String register(@Valid Teacher teacher,BindingResult result) {
   		if (result.hasErrors()) {
   			return "fail";
   		}
   		return "success";
   	}
}

Tips: @Valid 注解表示在绑定数据之后对数据进行验证。BindingResult 组件用来保存验证过程中的错误信息。除了可以使用 BindingResult ,此处还可以使用 Errors 替代。

  1. 在浏览器中访问到 teacher.html 页面,输入不符合规则的数据后提交(年龄小于 22 岁);

图片描述

  1. 最后会在浏览器中看到。
    图片描述

如此,整个验证过程完毕。

3. 显示错误信息

前面的测试过程有一个遗憾,没有看到错误信息,没有明确的告诉使用者哪些数据输入没有符合验证要求。

要实现这个功能,只需要在控制器中把错误信息保存到请求域,然后在页面中显示出来。

  1. 修改一下控制器中的代码。比前面的代码多了一个 ModelMap 对象,用于把错误信息保存到请求作用域中;
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String register(@Valid Teacher teacher, BindingResult result, ModelMap model) {
	if (result.hasErrors()) {
		List<FieldError> fieldsErrors = result.getFieldErrors();
		for (FieldError fieldError : fieldsErrors) {
			model.put(fieldError.getField(), fieldError.getDefaultMessage());
		}
		return "fail";
	}
	return "success";
 }

Tips: 如果验证失败,错误提示信息会自动保存到 BindingResult 类型 。

  1. 在提交失败的页面中显示错误。
<body>
老师注册失败原因!
<br/>
 ${name}
 <br/>
 ${age}
</body>

Tips: EL 表达式中的 name、age 是表单提交时的参数名(也就是表单控件的名字)。

model.put (fieldError.getField (), fieldError.getDefaultMessage ()) 这行代码会把错误信息以表单控件名为 key 保存在请求作用域中。

  1. 再次在浏览器中打开 teacher.html 页面,输入不符合规则的数据,提交后在错误页面中看到。

图片描述

4. 小结

本节课程和大家讲解了 Spring MVC 的验证框架,需要知道以下 2 点:

  • Spring MVC 验证框架采用的是服务器端验证模式;
  • Spring MVC 框架集成了 JSR 验证框架,并没有提供具体的实现,本课程使用的是 Hibernate 提供的 JSR 具体实现模块。

Spring MVC 验证框架以注解的方式对数据进行规则限制,方便,简洁,但因是服务器端验证,所以,对于一般性的、常规性的验证建议放在客户端完成。