前言:
Spring MVC提供了两种数据校验的方式:1.基于Validator接口,2.使用Annotaion JSR-303标准进行校验。
基于Validator接口的方式需要自定义Validator验证器,每一条数据的验证规则需要自己手动完成,使用Annotaion JSR-303标准则不需要自定义验证器,通过注解的方式可以直接在实体类中添加每个属性的校验规则,这种方式更加方便,实际开发中推荐使用。
基于Validator接口
我们通过学生登录的场景来学习使用基于Validator接口的验证器。
1.实体类Student。
package com.southwind.entity;
public class Student {
private String name;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.自定义校验器StudentValidation,实现Validator接口,覆盖其方法。
package com.southwind.validator;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import com.southwind.entity.Student;
public class StudentValidator implements Validator{
public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return Student.class.equals(clazz);
}
public void validate(Object target, Errors errors) {
// TODO Auto-generated method stub
ValidationUtils.rejectIfEmpty(errors, "name", null, "姓名不能为空");
ValidationUtils.rejectIfEmpty(errors, "password", null, "密码不能为空");
}
}
3.控制器HelloHandler,业务方法login参数列表中的@Validated表示参数student是需要校验的对象,@BindingResult用来存储错误信息,两者缺一不可,而且必须挨着写,不能中间有其他参数。
package com.southwind.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.southwind.entity.Student;
@Controller
@RequestMapping("/hello")
public class HelloHandler {
@GetMapping(value = "/login")
public String login(Model model){
model.addAttribute(new Student());
return "login";
}
@PostMapping(value="/login")
public String login(@Validated Student student,BindingResult br) {
if (br.hasErrors()) {
return "login";
}
return "success";
}
}
4.springmvc.xml中配置validator。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<!-- 配置自动扫描 -->
<context:component-scan base-package="com.southwind"></context:component-scan>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/"></property>
<!-- 后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 基于Validator的配置 -->
<mvc:annotation-driven validator="studentValidator"/>
<bean id="studentValidator" class="com.southwind.validator.StudentValidator"/>
</beans>
5.login.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>学生登录</h1>
<form:form modelAttribute="student" action="login" method="post">
学生姓名:<form:input path="name" /><form:errors path="name"/><br/>
学生密码:<form:password path="password" /><form:errors path="password"/><br/>
<input type="submit" value="提交"/>
</form:form>
</body>
</html>
6.运行,通过地址栏发送GET请求访问login方法,绑定模型数据,然后页面跳转到login.jsp。
直接点击提交按钮,form表单发送POST请求访问login方法,完成数据校验,并将校验结果再次返回到login.jsp。
Annotaion JSR-303标准
使用Annotation JSR-303标准进行验证,需要导入支持这种标准的jar包,这里我们使用Hibernate Validator。
标准详解:
限制 | 说明 |
---|---|
@Null | 限制只能为null |
@NotNull | 限制必须不为null |
@AssertFalse | 限制必须为false |
@AssertTrue | 限制必须为true |
@DecimalMax(value) | 限制必须为一个不大于指定值的数字 |
@DecimalMin(value) | 限制必须为一个不小于指定值的数字 |
@Digits(integer,fraction) | 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction |
@Future | 限制必须是一个将来的日期 |
@Max(value) | 限制必须为一个不大于指定值的数字 |
@Min(value) | 限制必须为一个不小于指定值的数字 |
@Past | 限制必须是一个过去的日期 |
@Pattern(value) | 限制必须符合指定的正则表达式 |
@Size(max,min) | 限制字符长度必须在min到max之间 |
@Past | 验证注解的元素值(日期类型)比当前时间早 |
@NotEmpty | 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0) |
@NotBlank | 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格 |
验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式 |
接下来我们通过用户注册的场景来学习使用JSR-303标准进行数据校验。
1.pom.xml添加Hibernate Validator依赖。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.southwind</groupId>
<artifactId>springmvc</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>springmvc Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!-- JRS-303 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.3.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.1.1.GA</version>
</dependency>
<!-- 解决JDK9以上版本没有JAXB API jar的问题,JDK9以下版本不需要配置 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<build>
<finalName>springmvc</finalName>
</build>
</project>
这里我们需要注意,如果你的环境是JDK9以下的,可以不用添加以下四个依赖。
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
如果你的环境是JDK9以上版本,必须添加这四个依赖。
2.创建实体类User,通过注解的方式给属性指定校验规则。
校验规则详解:
Constraint | 详细信息 |
---|---|
@Null | 被注释的元素必须为 null |
@NotNull | 被注释的元素必须不为 null |
@AssertTrue | 被注释的元素必须为 true |
@AssertFalse | 被注释的元素必须为 false |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@DecimalMax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Size(max, min) | 被注释的元素的大小必须在指定的范围内 |
@Digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@Past | 被注释的元素必须是一个过去的日期 |
@Future | 被注释的元素必须是一个将来的日期 |
@Pattern(value) | 被注释的元素必须符合指定的正则表达式 |
被注释的元素必须是电子邮箱地址 | |
@Length | 被注释的字符串的大小必须在指定的范围内 |
@NotEmpty | 被注释的字符串的必须非空 |
@Range | 被注释的元素必须在合适的范围内 |
User实体类。
package com.southwind.entity;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
public class User {
@NotEmpty(message = "用户名不能为空")
private String username;
@Size(min = 6,max = 20,message = "密码长度为6-12位")
private String password;
@Email(regexp = "^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*\\.[a-zA-Z0-9]{2,6}$", message = "请输入正确的邮箱格式")
private String email;
@Pattern(regexp = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\\\d{8}$",message="请输入正确的电话格式")
private String phone;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
3.控制器HelloHandler,业务方法register使用@Valid来绑定校验对象,@BindingResult来保存错误信息。
package com.southwind.controller;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.southwind.entity.User;
@Controller
@RequestMapping("/hello")
public class HelloHandler {
@GetMapping(value="/register")
public String register(Model model){
model.addAttribute(new User());
return "register";
}
@PostMapping(value="/register")
public String register2(@Valid User user,BindingResult br) {
if (br.hasErrors()){
return "register";
}
return "success";
}
}
4.springmvc.xml配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<!-- 配置自动扫描 -->
<context:component-scan base-package="com.southwind"></context:component-scan>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/"></property>
<!-- 后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- JSR-303配置 -->
<mvc:annotation-driven />
</beans>
5.register.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>用户注册</h1>
<form:form modelAttribute="user" action="register" method="post">
用户名:<form:input path="username" /><form:errors path="username" /><br/>
密码:<form:password path="password" /><form:errors path="password" /><br/>
邮箱:<form:input path="email" /><form:errors path="email" /><br/>
电话:<form:input path="phone" /><form:errors path="phone" /><br/>
<input type="submit" value="提交"/>
</form:form>
</body>
</html>
6.运行,通过地址栏发送GET请求访问register方法,绑定模型数据,然后页面跳转到register.jsp。
直接点击提交按钮,form表单发送POST请求访问register方法,完成数据校验,并将校验结果再次返回到register.jsp。