java bean 验证——JSR 380
概述
本文快速浏览下java bean验证的基础知识,使用jsr380标准框架,也就是Bean validation2.0 。
验证用户输入,在大多数应用中是最常用的需求,java bean 验证框架已经称为处理这方面逻辑的实时标准。
JSR 380
JSR 380规范是bean验证的java api规范,javaEE和javaSE的一部分,使用注解如@NotNull, @Min, and @Max,确保bean属性符合一定条件。
jsr380需要java8或以上版本,利用java8中新增的特性,如注解类型,支持新的类如:Optional 和 LocalDate。点击查看完整jsr380规范.
依赖
我们使用maven方式引入jar,也可以使用其他方式,如gradle。
验证API
根据jsr380规范,validation-api依赖库包含标准validation api:
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.0.Final</version>
</dependency>
验证API参考实现
Hibernate Validator是验证规范的参考实现,我们需要增加下面依赖:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.2.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.0.2.Final</version>
</dependency>
需要注意的是,hibernate-validator与Hibernate持久化功能完全独立,这里并没有引入持久化方面的库。
表达式依赖
jsr380提供了变量插入功能,允许表达式在错误信息中混合使用。为了解析表达式,我们必须增加下面依赖:表达式语言API及其实现,GlassFish提供了参考实现:
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
如果没有增加表达式库,会报错,信息如下:
HV000183: Unable to load ‘javax.el.ExpressionFactory’. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
使用验证注解
我们使用User bean 作为主要示例,并增加一些验证注解:
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraints.Email;
public class User {
@NotNull(message = "Name cannot be null")
private String name;
@AssertTrue
private boolean working;
@Size(min = 10, max = 200, message = "About Me must be between 10 and 200 characters")
private String aboutMe;
@Min(value = 18, message = "Age should not be less than 18")
@Max(value = 150, message = "Age should not be greater than 150")
private int age;
@Email(message = "Email should be valid")
private String email;
// standard setters and getters
}
上面使用的注解是jsr标准的注解:
@NotNull – 验证注解的属性值不能为 null
@AssertTrue – 验证注解的属性值为 true
@Size – 验证注解的属性值大小在max和min之间,也可以应用在 String, Collection, Map, array 属性
@Min – 验证注解的属性值不小于value属性指定的值
@Max – 验证注解的属性值不大于value属性指定的值
@Email – 验证注解的属性值是一个有效的email地址
一些注解还有其他属性,但message 属性是通用的,没有注解都有。当属性值验证失败是用于信息提示。
JSR 中其他一些注解如下:
@NotEmpty – 验证注解的属性值不为 null 或 empty; 可以应用在String, Collection, Map 或 Array 值
@NotBlank – 验证注解的属性值不为 null 或 whitespace,应用在字符串值验证
@Positive 和 @PositiveOrZero – 验证注解的属性值大于等于零,应用在数值验证
@Negative 和 @NegativeOrZero – 验证注解的属性值小于等于零,应用在数值验证
@Past 和 @PastOrPresent – 验证注解的属性值为过去时间或包括现在,应用在日期验证,支持java8日期类型
@Future 和 @FutureOrPresent – 验证注解的属性值为将来时间或包括现在,应用在日期验证,支持java8日期类型
验证注解也可以应用于集合元素:
List<@NotBlank String> preferences;
这时,list中增加任何值将触发验证.
验证规范也支持 Java 8 Optional 类型 :
private LocalDate dateOfBirth;
public Optional<@Past LocalDate> getDateOfBirth() {
return Optional.of(dateOfBirth);
}
这里,验证框架会自动抽出LocalDate值并验证.
可编程验证
一些框架,如spring,使用注解让验证过程非常简单。主要是为了不让我们和验证api通过编程方式交互,简化框架应用。
现在让我们手工实现编程方式验证:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
验证bean,首先需要validator,通过ValidatorFactory可以获得。
定义Bean
我们现在定义一个无效的user对象,name为null:
User user = new User();
user.setWorking(true);
user.setAboutMe("Its all about me!");
user.setAge(50);
验证bean
前面已经获得Validator,把需要验证的对象user传入validate方法进行验证,user中任何一个违法约束将被返回至Set。
Set<ConstraintViolation<User>> violations = validator.validate(user);
迭代Set集合,可以getMessage 获得所有错误信息。
for (ConstraintViolation<User> violation : violations) {
log.error(violation.getMessage());
}
上面示例中name为null,所以包括一个错误信息,“Name cannot be null”。
总结
本文简要浏览了java 验证规范,并通过注解演示了基本的验证过程。