SpringMVC教程之JSR303数据校验

一、前言

JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中,JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean 进行验证。

JSR303定义的校验类型如下:

空检查
	@Null 验证对象是否为null
	@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
	@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
	@NotEmpty 检查约束元素是否为NULL或者是EMPTY.
Booelan检查
	@AssertTrue 验证 Boolean 对象是否为 true
	@AssertFalse 验证 Boolean 对象是否为 false
长度检查
	@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
	@Length(min=, max=) Validates that the annotated string is between min and max included.
日期检查
	@Past 验证 Date 和 Calendar 对象是否在当前时间之前
	@Future 验证 Date 和 Calendar 对象是否在当前时间之后
	@Pattern 验证 String 对象是否符合正则表达式的规则
数值检查
	建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为String为"",Integer为null
@Min 验证 Number 和 String 对象是否大等于指定的值
@Max 验证 Number 和 String 对象是否小等于指定的值
@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits 验证 Number 和 String 的构成是否合法
@Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。
@Range(min=, max=) 检查数字是否介于min和max之间.
@Range(min=10000,max=50000,message="range.bean.wage")
private BigDecimal wage;
@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
@CreditCardNumber信用卡验证
@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。
@ScriptAssert(lang= ,script=, alias=)
@URL(protocol=,host=, port=,regexp=, flags=)

Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解:

@Email 被注释的的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定范围内
@NotEmpty 被注释的字符串必须非空
@Range 被注释的元素必须在合适的范围内

下面通过简单例子来学习一下。

二、案例

♦准备校验时使用的JAR

<dependency>
	<groupId>javax.validation</groupId>
	<artifactId>validation-api</artifactId>
	<version>1.0.0.GA</version>
</dependency>
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-validator</artifactId>
	<version>4.2.0.Final</version>
</dependency>

♦编写需要校验的bean

import java.util.Date;

import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.format.annotation.DateTimeFormat;

/**
 * @author queen
 * @since 2017-11-12
 */
public class User {
	private Integer id;
	// 用户名
	@NotBlank(message = "名字不能为空")
	private String userName;
	// 密码
	@NotBlank(message = "密码不能为空")
	private String password;
	// 邮箱
	@NotBlank(message = "邮箱不能为空")
	@Email(message = "邮箱格式错误")
	private String email;
	// 年龄
	@NotNull(message = "年龄不能为空")
	@Max(value = 120, message = "年龄最大不能超过120")
	private Integer age;
	// 雇佣日期
	@NotNull(message = "雇佣日期不能为空")
	@DateTimeFormat(pattern = "yyyy-MM-dd")
	private Date hireTime;

	public User() {
	}

	public User(Integer id, String userName, String password, String email,
			Integer age, Date hireTime) {
		this.id = id;
		this.userName = userName;
		this.password = password;
		this.email = email;
		this.age = age;
		this.hireTime = hireTime;
	}

	public Date getHireTime() {
		return hireTime;
	}

	public void setHireTime(Date hireTime) {
		this.hireTime = hireTime;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	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 Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", userName=" + userName + ", password="
				+ password + ", email=" + email + ", age=" + age
				+ ", hireTime=" + hireTime + "]";
	}

}

需要注意的是:使用hibernate validator容易出现以下的错误

Nov 12, 2017 2:13:57 PM org.apache.catalina.core.StandardWrapperValve invoke  
SEVERE: Servlet.service() for servlet springmvc threw exception  
javax.validation.UnexpectedTypeException: No validator could be found for type: java.lang.Integer  
    at org.hibernate.validator.engine.ConstraintTree.verifyResolveWasUnique(ConstraintTree.java:383)  
    at org.hibernate.validator.engine.ConstraintTree.findMatchingValidatorClass(ConstraintTree.java:364)  
    at org.hibernate.validator.engine.ConstraintTree.getInitializedValidator(ConstraintTree.java:313)  
    at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:144)  
    at org.hibernate.validator.engine.ConstraintTree.validateComposingConstraints(ConstraintTree.java:233)  
    at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:128)  
    at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:117)  
    at org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:84)  
    at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:452)  

@NotNull 和 @NotEmpty 和@NotBlank 区别

  • @NotEmpty 用在集合类上面
  • @NotBlank 用在String上面
  • @NotNull  用在基本类型上

如果在基本类型上面用NotEmpty或者NotBlank 会出现上面的错

♦校验方法

/**
 * @author queen
 * @since 2017-11-7
 */
@RequestMapping("/user")
@Controller
public class UserHandler {
	
	@RequestMapping(value = "/dataValidate", method = RequestMethod.POST)
	public String dataValidate(@Valid User user, BindingResult result) {
		if(result.getErrorCount()>0){
			System.out.println("出错了!");
			for(FieldError error:result.getFieldErrors()){
				System.out.println(error.getField() + ":" + error.getDefaultMessage());
			}
		}
		return "success";
	}
}

需要注意:我们的处理器方法必须给定包含Errors的参数,这可以是Errors本身,也可以是它的子类BindingResult,使用了Errors参数就是告诉Spring关于表单对象数据校验的错误将由我们自己来处理,否则Spring会直接抛出异常,而且这个参数是必须紧挨着@Valid参数的,即必须紧挨着需要校验的参数,这就意味着我们有多少个@Valid参数就需要有多少个对应的Errors参数,它们是一一对应的,例如:

SpringMVC教程之JSR303数据校验的照片 - 1

♦测试页面userAdd.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试页面</title>
</head>
<body>
	<form action="user/dataValidate" method="Post">
		名字: <input type="text" name="username"/>
		<br>
		密码: <input type="text" name="password" />
		<br>
		邮箱: <input type="text" name="email"/>
		<br>
		年龄: <input type="text" name="age"/>
		<br>
		<input type="submit" value="提交"/>
	</form>
</body>
</html>

♦响应界面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>success</title>
</head>
<body>
	${username }
	<br>
	${password }
	<br>
	${email }
	<br>
	${age }
	<br>
	${hireTime }
</body>
</html>

♦springmvc配置

<?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:p="http://www.springframework.org/schema/p"
	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-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	<!-- 定义Controller的扫描包 -->
	<context:component-scan base-package="com.queen.springmvc" />

	<!-- 配置视图解析器 -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>

	<mvc:annotation-driven></mvc:annotation-driven>
</beans>

♦启动运行

SpringMVC教程之JSR303数据校验的照片 - 3

在没有录入数据的情况下,数据校验成功。

我们再测试一下别的情况:

SpringMVC教程之JSR303数据校验的照片 - 5

邮箱格式错误,年龄超过最大值,雇佣时间输入没有按照指定的格式,这些SpringMVC在数据绑定的时候进行了数据类型转换,数据格式化处理,并将处理后的结果放到了BindingResult中,界面上显示的提示信息都是从BindingResult中取出来,经过处理后放到请求域中显示出来。

至此,我们关于SpringMVC教程之JSR303数据校验介绍完毕。想要了解更多关于SpringMVC开发的教程,请参考http://www.marsitman.com/springmvc
博客地址:http://www.marsitman.com/springmvc/springmvc-data-valid.html
版权声明:本文为博主原创文章,允许转载,但转载必须标明出处。

 

 

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!



点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注