内容简介:掌握Java-Bean Validation
数据校验虽然简单,但是却是一个繁琐的事。我在无数的代码看到if判断参数,然后错了打日志抛异常,一片一片的这种代码,如果有点重复了,再弄出N个xxUtil来归纳代码。虽然这种做法可以达到效果,但是代码散乱,一个是编写麻烦,一个是不易阅读。
Java业界最喜欢搞规范,所以参数校验作为一个痛点,JSR 303 - Bean Validation规范出现了。
JSR 303 – Bean Validation 是一个数据验证的规范,2009年11月确定最终方案。2009年12月Java EE 6发布,Bean Validation作为一个重要特性被包含其中。Hibernate Validator是 Bean Validation 的参考实现。Hibernate Validator提供了JSR 303规范中所有内置constraint的实现,除此之外还有一些附加的constraint。
constraint就是约束条件,比如不能为空之类的,这些条件被定义,然后就能被复用,而不是每次都在if语句里写。Bean Validation为Bean的验证定义了元数据模型和API,这里的元数据就是constant,元数据默认的形式是注解,还可以使用xml来定义constraint。
引入Bean Validation
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.2.Final</version>
</dependency>
<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>
例子
我们先看看Bean Validation怎么用,有个大体的认识。首先声明需要被校验的Java Bean:
public class User{
@NotNull(message = "用户名不能为空")
private String name;
@Min(value = 1, message = "年龄不能小于1")
@Max(value = 200, message = "年龄不能大于200")
private int age;
// 构造函数,getter,setter略
}
在User Bean中我们使用了几个注解来修饰字段,name字段上添加 @NotNull
表示这个字段不能为空,age字段上添加 @Min
和 @Max
注解,表示限制其最大和最小值。这些constraint注解是Bean Validation规范内置的。全部内置的constraint说明见下文。
然后编写入口函数,实例化Bean并进行校验:
public static void main(String[] args){
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<User>> validate = validator.validate(new User(null, 0));
for (ConstraintViolation<User> violation : validate) {
System.out.println(violation.getMessage());
}
}
输出:
用户名不能为空 年龄不能小于1
Bean Validation内置constraint
JSR 303内置了常用的constraint,我们可以直接使用。
空检查
-
@Null被注释的元素必须为 null (任何类型) -
@NotNull被注释的元素必须不为 null (任何类型)
布尔检查
-
@AssertTrue被注释的元素必须为 true (boolean或者Boolean) -
@AssertFalse被注释的元素必须为 false (boolean或者Boolean)
数字检查
-
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值 (BigDecimal,BigInteger,byte,short,int,long及其包装类) -
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值 -
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值 (CharSequence,BigDecimal,BigInteger,byte,short,int,long及其包装类) -
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值 -
@Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内 (BigDecimal,BigInteger,byte,short,int,long及其包装类)
字符串(集合)检查
-
@Size(max, min)被注释的元素的大小必须在指定的范围内 (CharSequence,Collection,Map,Array) -
@Pattern(value)被注释的元素必须符合指定的正则表达式 (CharSequence)
时间检查
-
@Past被注释的元素必须是一个过去的日期 (Date,Calendar) -
@Future被注释的元素必须是一个将来的日期 (Date,Calendar)
Hibernate Validator扩展的constraint
Hibernate除了实现标准的constraint,还实现了一些扩展constraint。
-
@NotEmpty被注释的字符串的必须非空 -
@NotBlank被注释的字符串的必须非空白 -
@Range被注释的元素必须在合适的范围内 (内部使用@Min和@Max实现) -
@Length被注释的字符串的大小必须在指定的范围内(同@Size) -
@URL被注释的字符串必须是合法的URL -
@Email被注释的元素必须是电子邮箱地址 -
@SafeHtml被注解的字符串必须是合法的HTML -
@CreditCardNumber被注释的元素必须是合法的信用卡号,使用的是Luhn算法 -
@ScriptAssert直接指定脚本进行校验,算是最灵活的了
自定义Constraint
虽然Bean Validation规范提供了内置的constraint,但是对于实际使用来说是根本不够用的,业务的规则千奇百怪,是需要自己自定义constraint的。
定制一个constraint需要两个部分,一个是constraint注解,一个是执行校验逻辑的类。
比如我们想要定制一个UUID格式字符串的constraint,可以这么写:
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = UUIDValidator.class)
public @interface UUID {
Stringmessage()default "UUID不合法";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
constraint注解需要使用 @Constraint(validatedBy = UUIDValidator.class)
来指定这个注解是一个Bean Validation注解,并且指定对应的校验规则实现类。
同时,constraint注解必须是 @Retention(RetentionPolicy.RUNTIME)
,因为在运行是需要使用到注解。
然后编写校验规则实现类:
public class UUIDValidatorimplements ConstraintValidator<UUID,String>{
public static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}");
@Override
public void initialize(UUID uuid){
}
@Override
public boolean isValid(String object, ConstraintValidatorContext constraintValidatorContext){
if (object == null){
return true;
}
return UUID_PATTERN.matcher(object).matches();
}
}
实现类需要实现 ConstraintValidator<A extends Annotation, T>
接口,泛型参数 A
指定该类作用于什么constraint注解上, T
指定这个校验规则作用于什么数据类型。
因为一个constraint注解是可以作用于多种数据类型上的,比如 @Size
即可用于String上,也可以用于集合上,如何做到的呢?就是为一个constraint注解实现多个校验规则实现类,并指定不同的 T
参数。
Bean Validation 2.0
上面说的都是Bean Validation 1.0和1.1。这两个分别是在JavaEE6和JavaEE7中的。对应的JSR是JSR 303。
在2017年8月, Bean Validation 2.0 发布了。
Bean Validation 2.0是JavaEE8的一部分,只支持 Java 8+。对应的JSR是JSR 380。
Bean Validation的新功能:
-
支持验证泛型参数,比如
List<@Positive Integer> positiveNumbers-
可以更灵活的验证集合中的Bean,比如
Map<@Valid CustomerType, @Valid Customer> customersByType -
支持
java.util.Optional - 支持JavaFX声明的属性
-
可以更灵活的验证集合中的Bean,比如
-
@Past和@Futur支持JSR 310的时间类型 - 新增内置constraint:@Email, @NotEmpty, @NotBlank, @Positive, @PositiveOrZero, @Negative, @NegativeOrZero, @PastOrPresent and @FutureOrPresent
- 所有的内置constraint都是repeatable的
-
ConstraintValidator#initialize()是default方法,可选实现
引入Bean Validation 2.0:
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.0.Final</version>
</dependency>
<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>
<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>
以上所述就是小编给大家介绍的《掌握Java-Bean Validation》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
淘宝、天猫电商运营百科全书
刘涛 / 电子工业出版社 / 2016-7 / 59.00元
有人说淘宝、天猫上90%的卖家不赚钱,我认为说得有点大了。因为如果说大家都不赚钱或者在亏钱,为什么去年在做店铺的卖家,今年还在继续?那些不赚钱的卖家,多数是没意识到市场的变化,还在用原来的套路运营店铺。市场在变,但卖家的思路却没有转变,不赚钱也在情理之中,因为淘宝、天猫的玩法变了。做店铺就是好比一场“打怪”升级的游戏,每次的升级都需要强大的装备与攻略。优胜劣汰,能活下去并且能赚钱的卖家,都是在不停......一起来看看 《淘宝、天猫电商运营百科全书》 这本书的介绍吧!