美文网首页
Java Bean Validation

Java Bean Validation

作者: postSuperMan | 来源:发表于2018-10-21 16:42 被阅读0次

    Java Bean Validation

    参数校验是我们程序开发中必不可少的过程。用户在前端页面上填写表单时,前端js程序会校验参数的合法性,当数据到了后端,为了防止恶意操作,保持程序的健壮性,后端同样需要对数据进行校验。后端参数校验最简单的做法是直接在业务方法里面进行判断,当判断成功之后再继续往下执行。但这样带给我们的是代码的耦合,冗余。当我们多个地方需要校验时,我们就需要在每一个地方调用校验程序,导致代码很冗余,且不美观。

    那么如何优雅的对参数进行校验呢?JSR303就是为了解决这个问题出现的,本篇文章主要是介绍 JSR303,Hibernate Validator 等校验工具的使用,以及自定义校验注解的使用。

    校验框架介绍

    JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。注解如下:

    Bean Validation是一个通过配置注解来验证参数的框架,它包含两部分Bean Validation API和Hibernate Validator。

    1. Bean Validation 中内置的 constraint
    image
    1. Hibernate Validator 附加的 constraint (hibernate补充的注解中,最后3个不常用,可忽略)
    image

    @NotNull @NotEmpty @NotBlank 3个注解的区别:

    @NotNull 任何对象的value不能为null

    @NotEmpty 集合对象的元素不为0,即集合不为空,也可以用于字符串不为null

    @NotBlank 只能用于字符串不为null,并且字符串trim()以后length要大于0

    Spring validtor 同样扩展了jsr303,并实现了方法参数和返回值的校验

    Spring 提供了MethodValidationPostProcessor类,用于对方法的校验

    第一步:pom.xml引入依赖

    image

    第二步:JavaBean 添加校验注解

    image

    第三步:@Valid参数校验

    image

    注意事项:使用@Valid 参数校验时,如果参数校验不过,则回抛出400 异常

    扩展知识:自定义校验注解

    虽然jSR303和Hibernate Validtor 提供了很多注解,但在实际使用中,往往不能满足使用需求,需要进行组合,更复杂的校验方式。

    1.分组验证:

    同一javabean, 但根据不同的业务逻辑进行参数校验,例如新增or修改

    1.1 定义两个空接口

    /**
     * 可以在一个Model上面添加多套参数验证规则,此接口定义添加Person模型新增时的参数校验规则
     */
    public interface PersonAddView {
    }
    
    /**
     * 可以在一个Model上面添加多套参数验证规则,此接口定义添加Person模型修改时的参数校验规则
     */
    public interface PersonModifyView {
    }
    

    1.2 添加注解时使用指明所述的分组

    public class Person {
        private long id;
        /**
         * 添加groups 属性,说明只在特定的验证规则里面起作用,不加则表示在使用Deafault规则时起作用
         */
        @NotNull(groups = {PersonAddView.class, PersonModifyView.class}, message = "添加、修改用户时名字不能为空", payload = ValidateErrorLevel.Info.class)
        @ListNotHasNull.List({
                @ListNotHasNull(groups = {PersonAddView.class}, message = "添加上Name不能为空"),
                @ListNotHasNull(groups = {PersonModifyView.class}, message = "修改时Name不能为空")})
        private String name;
    
        @NotNull(groups = {PersonAddView.class}, message = "添加用户时地址不能为空")
        private String address;
    
        @Min(value = 18, groups = {PersonAddView.class}, message = "姓名不能低于18岁")
        @Max(value = 30, groups = {PersonModifyView.class}, message = "姓名不能超过30岁")
        private int age;
      //getter setter 方法......
    }
    

    1.3 启用校验(指定组)

    /**
         * 添加一个Person对象
         * 此处启用PersonAddView 这个验证规则
         * 备注:此处@Validated(PersonAddView.class) 表示使用PersonAndView这套校验规则,若使用@Valid 则表示使用默认校验规则,
         * 若两个规则同时加上去,则只有第一套起作用
         */
        @RequestMapping(value = "/person", method = RequestMethod.POST)
        public void addPerson(@RequestBody @Validated({PersonAddView.class, Default.class}) Person person) {
            System.out.println(person.toString());
        }
    
        /**
         * 修改Person对象
         * 此处启用PersonModifyView 这个验证规则
         */
        @RequestMapping(value = "/person", method = RequestMethod.PUT)
        public void modifyPerson(@RequestBody @Validated(value = {PersonModifyView.class}) Person person) {
            System.out.println(person.toString());
        }
    

    2.List参数校验:

    2.1 定义注解

    package com.test.validate.annotation;
    
    import javax.validation.Constraint;
    import javax.validation.Payload;
    import java.lang.annotation.*;
    
    import static java.lang.annotation.ElementType.*;
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    /**
     * 自定义参数校验注解
     * 校验 List 集合中是否有null 元素
     */
    
    @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Constraint(validatedBy = ListNotHasNullValidatorImpl.class)//此处指定了注解的实现类为ListNotHasNullValidatorImpl
    
    public @interface ListNotHasNull {
    
        /**
         * 添加value属性,可以作为校验时的条件,若不需要,可去掉此处定义
         */
        int value() default 0;
    
        String message() default "List集合中不能含有null元素";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    
        /**
         * 定义List,为了让Bean的一个属性上可以添加多套规则
         */
        @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
        @Retention(RUNTIME)
        @Documented
        @interface List {
            ListNotHasNull[] value();
        }
    }
    

    2.2 实现注解方法

    package com.test.validate.annotation;
    
    import javax.validation.Constraint;
    import javax.validation.Payload;
    import java.lang.annotation.*;
    
    import static java.lang.annotation.ElementType.*;
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    /**
     * 自定义参数校验注解
     * 校验 List 集合中是否有null 元素
     */
    @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Constraint(validatedBy = ListNotHasNullValidatorImpl.class)////此处指定了注解的实现类为ListNotHasNullValidatorImpl
    
    public @interface ListNotHasNull {
    
        /**
         * 添加value属性,可以作为校验时的条件,若不需要,可去掉此处定义
         */
        int value() default 0;
    
        String message() default "List集合中不能含有null元素";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    
        /**
         * 定义List,为了让Bean的一个属性上可以添加多套规则
         */
        @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
        @Retention(RUNTIME)
        @Documented
        @interface List {
            ListNotHasNull[] value();
        }
    }
    

    2.3 使用注解

    public class User {
    
        //其他参数 .......
    
        /**
         * 所拥有的书籍列表
         */
        @NotEmpty(message = "所拥有书籍不能为空")
        @ListNotHasNull(message = "List 中不能含有null元素")
        @Valid
        private List<Book> books;
        //getter setter 方法.......
    }
    

    相关文章

      网友评论

          本文标题:Java Bean Validation

          本文链接:https://www.haomeiwen.com/subject/qtbbzftx.html