Bean Validation 介绍和简单应用 (初学者笔记)

  • 一、概述
  1. 目的

在一个应用的不同层面(例如表现层到持久层),验证数据是一个是反复共同的任务。许多时候相同的验证要在每一个独立的验证框架中出现很多次。为了提升开发效率,阻止重复造轮子,于是形成了这样一套规范。

开发人员经常将验证逻辑直接绑定到域模型中,使用验证代码将域类与类本身的元数据绑定在一起。

 

2. 简要介绍

方法一:后端参数校验最简单的做法是直接在业务方法里面进行判断,当判断成功之后再继续往下执行。

优点:简单,直接

缺点:代码的耦合,冗余,不美观。

方法二:使用BeanValidation(JSR380)规则。

JSR-380是JAVAEE6中的一项子规范,叫做BeanValidation,官方参考实现是HibernateValidator。此实现与Hibernate ORM没有任何关系。JSR380用于对JavaBean中的字段的值进行验证。SpringMVC3.x之中也大力支持JSR-303,可以在控制器中对表单提交的数据方便地验证。可以使用注解的方式进行验证。

该规范定义了一个元数据模型,默认的元数据来源是注解(annotation)。针对该规范的验证API不是为某一个编程模型来开发的,因此它不束缚于Web或者持久化。

3. 概念

BeanValidation是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回,是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。

4. 特点

  • BeanValidation验证符合标准的Java规范
  • 让您通过注释来表达对对象模型的约束
  • 让您以可扩展的方式编写自定义约束
  • 提供用于验证对象和对象图的api
  • 提供用于验证参数和返回方法和构造函数值的api
  • 运行在JavaSE上,但是集成在JavaEE6和以后;Bean验证2.0是JavaEE8的一部分

 版本303,349,380(Bean Validation2)

5. 网站

  1. Java官网,The Java Community Process(SM) Program - JSRs: Java Specification Requests - detail JSR# 303
  2. hibernate官网,Page Redirection
  3. hibernateapi官方文档,http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-gettingstarted-createproject
  4. beanvalidation官方api文档,https://docs.oracle.com/javaee/6/api/javax/validation/constraints/package-summary.html
  5. beanvalidation官网,Jakarta Bean Validation - Home
  6. beanvalidation2官方学习文档,https://beanvalidation.org/2.0/spec/

二、BeanValidation具体注释

原生注释:

空检查
@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=)Validatesthattheannotatedstringisbetweenminandmaxincluded.

日期检查
@Past验证Date和Calendar对象是否在当前时间之前,验证成立的话被注释的元素一定是一个过去的日期
@Future验证Date和Calendar对象是否在当前时间之后,验证成立的话被注释的元素一定是一个将来的日期
@Pattern验证String对象是否符合正则表达式的规则,被注释的元素符合制定的正则表达式,regexp:正则表达式flags:指定Pattern.Flag的数组,表示正则表达式的相关选项。

数值检查
建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为”“,Integer为null
@Min验证Number和String对象是否大等于指定的值
@Max验证Number和String对象是否小等于指定的值
@DecimalMax被标注的值必须不大于约束中指定的最大值.这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin被标注的值必须不小于约束中指定的最小值.这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits验证Number和String的构成是否合法
@Digits(integer=,fraction=)验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。
@Range(min=,max=)被指定的元素必须在合适的范围内
@Range(min=10000,max=50000,message=”range.bean.wage”)
@Valid递归的对关联对象进行校验,如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
@CreditCardNumber信用卡验证
@Email验证是否是邮件地址,如果为null,不进行验证,算通过验证。
@ScriptAssert(lang=,script=,alias=)
@URL(protocol=,host=,port=,regexp=,flags=)

Hibernate扩展

 

  • 三、简单使用
  1. 添加依赖

<!--jsr380-->

<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!--hibernatevalidator-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.10.Final</version>
</dependency>
<!--非必须,但是在一些情况下它是必须的,因为BeanValidation需要EL表达式相应的支持-->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b08</version>
</dependency>

2. 简单的校验注释

packagecom.xxjz.java.com.xxjz.java.util.beanValid.pojo;

importjavax.validation.constraints.Min;
importjavax.validation.constraints.NotNull;
importjavax.validation.constraints.Size;

publicclassCar{
//品牌
@NotNull(message="品牌不能为空")
privateStringmanufacturer;

//牌照
@NotNull(message="不能为空")
@Size(min=2,max=14) (message="数值超出范围")
privateStringlicensePlate;

//座数
@Min(2)
privateintseatCount;

publicCar(Stringmanufacturer,StringlicensePlate,intseatCount){
this.manufacturer=manufacturer;
this.licensePlate=licensePlate;
this.seatCount=seatCount;
}

publicStringgetManufacturer(){
returnmanufacturer;
}

publicvoidsetManufacturer(Stringmanufacturer){
this.manufacturer=manufacturer;
}

publicStringgetLicensePlate(){
returnlicensePlate;
}

publicvoidsetLicensePlate(StringlicensePlate){
this.licensePlate=licensePlate;
}

publicintgetSeatCount(){
returnseatCount;
}

publicvoidsetSeatCount(intseatCount){
this.seatCount=seatCount;
}
}

3. 在springMVC框架中使用

@Controller
public class BeanValidController {
    @RequestMapping(value = "/valid",method = RequestMethod.POST)
    public String addCar(@RequestBody @Valid Car car){
        System.out.println("====");
        System.out.println(car.toString());
        return car.toString();
    }
}

4. 在java使用

Public static void main(String[]args){
Car car=newCar(null,"123451234567",1);
ValidatorFactoryfactory=Validation.buildDefaultValidatorFactory();
Validatorvalidator=factory.getValidator();
Set<ConstraintViolation<Car>>set=validator.validate(car);
for(ConstraintViolationv:set){
System.out.println(v.getMessage());
}
}

  • 四、高级功能
  1. 自定义校验注解

虽然jSR303和HibernateValidtor已经提供了很多校验注解,但是当面对复杂参数校验时,还是不能满足我们的要求,这时候我们就需要自定义校验注解。

             a. 定义注解

packagecom.xxjz.validate.annotation;

importjavax.validation.Constraint;

importjavax.validation.Payload;

importjava.lang.annotation.*;

importstaticjava.lang.annotation.ElementType.*;

importstaticjava.lang.annotation.ElementType.PARAMETER;

importstaticjava.lang.annotation.RetentionPolicy.RUNTIME;

/**

*自定义参数校验注解

*校验List集合中是否有null元素

*/

@Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD,ElementType.FIELD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Constraint(validatedBy=ListNotHasNullValidatorImpl.class)此处指定了注解的实现类为ListNotHasNullValidatorImpl

public@interfaceListNotHasNull{

/**

*添加value属性,可以作为校验时的条件,若不需要,可去掉此处定义

*/

intvalue()default0;

Stringmessage()default"List集合中不能含有null元素";

Class<?>[]groups()default{};

Class<?extendsPayload>[]payload()default{};

/**

*定义List,为了让Bean的一个属性上可以添加多套规则

*/

@Target({METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER})

@Retention(RUNTIME)

@Documented

@interfaceList{

ListNotHasNull[]value();

}

}

            b. 实现注解类:

packagecom.beiyan.validate.annotation;

importorg.springframework.stereotype.Service;

importjavax.validation.ConstraintValidator;

importjavax.validation.ConstraintValidatorContext;

importjava.util.List;

/**

*自定义注解ListNotHasNull的实现类

*用于判断List集合中是否含有null元素

*/

@Service

publicclassListNotHasNullValidatorImplimplementsConstraintValidator<ListNotHasNull,List>{

privateintvalue;

@Override

publicvoidinitialize(ListNotHasNullconstraintAnnotation){

//传入value值,可以在校验中使用

this.value=constraintAnnotation.value();

}

publicbooleanisValid(Listlist,ConstraintValidatorContextconstraintValidatorContext){

for(Objectobject:list){

if(object==null){

//如果List集合中含有Null元素,校验失败

returnfalse;

}

}

returntrue;

}

}

            c. 添加注解

publicclassUser{

//其他参数.......

/**

*所拥有的书籍列表

*/

@NotEmpty(message="所拥有书籍不能为空")

@ListNotHasNull(message="List中不能含有null元素")

@Valid

privateList<Book>books;

//gettersetter方法.......

}

2. 方法级别的校验

JSR和Hibernatevalidator的校验只能对Object的属性进行校验,不能对单个的参数进行校验,spring在此基础上进行了扩展,添加了MethodValidationPostProcessor拦截器,可以实现对方法参数的校验,实现如下:

                  a. 实例化MethodValidationPostProcessor

@Bean

Public MethodValidationPostProcessor methodValidationPostProcessor(){

Return new MethodValidationPostProcessor();

}

                  b. 在所要实现方法参数校验的类上面添加@Validated

@RestController

@Validated

publicclassValidateController{

}

                   c. 在方法上面添加校验规则

@RequestMapping(value="/test",method=RequestMethod.GET)

publicStringparamCheck(@Length(min=10)@RequestParamStringname){

System.out.println(name);

returnnull;

}

                  d. 当方法上面的参数校验失败,spring框架就回抛出异常

{

"timestamp":1476108200558,

"status":500,

"error":"InternalServerError",

"exception":"javax.validation.ConstraintViolationException",

"message":"Nomessageavailable",

"path":"/test"

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锁住子锁不住

老少爷们向前冲!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值