• Spring Validation-用注解代替代码参数校验


    Spring Validation

    概念

    在原先的编码中,我们如果要验证前端传递的参数,一般是在接受到传递过来的参数后,手动在代码中做 if-else 判断,这种编码方式会带来大量冗余代码,十分的不优雅。


    因此,推出了用注解的方式,来代替手动判断的方式,让编码更加的简洁。

    使用方式

    引入注解:
    一般在

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    

    依赖中会有相关依赖,如果没有的话,可以手动引入下面的依赖。

        <dependency>
          <groupId>org.hibernate.validator</groupId>
          <artifactId>hibernate-validator</artifactId>
          <version>6.0.18.Final</version>
          <scope>compile</scope>
        </dependency>
    

    get

    针对 get 方式的请求,我们的请求参数直接放在参数列表里,因此直接在参数列表里加上想要验证的注解即可。

      @GetMapping("xss")
        public void xssGet(@RequestParam("xss1") @Size(min = 1,max = 15,message = "长度不对") String xss, HttpServletRequest request) {
          
        }
    

    在方法中,需要验证 xss 参数是否符合长度规范,即长度在 1-15 个字符之间,如果不对,则会提示出信息:长度不对。

    post

    在 post 方法中,传递的参数一般比较多,因此大多数情况下,采用的是传递的实体类的形式,然后用 json 的形式来传递数据,在这种情况下,使用的方式为构建一个实体类,然后在实体类的属性上添加注解来做。

    @Data
    public class SaveEmployeeParam implements Serializable {
        private static final long serialVersionUID = 8176094330224588795L;
    
        @NotEmpty
        private String Id;
    
        @Size(max = 15, message = "名称必填,且最多为15个汉字")
        private String nickname;
    
        @PhoneValidationAnnotation
        private String phone;
    }
    
    
        @PostMapping
        public ResultEntity saveEmployee( @Valid @RequestBody SaveEmployeeParam saveEmployeeParam) {
            employeeService.saveEmployee(saveEmployeeParam);
            return ResultEntity.success();
        }
    

    通过该方式,在验证 SaveEmployeeParam 时,框架就会自动在接受参数时,验证实体类中的值是否符合注解定义的规范。


    在这里,就会验证 id 不能为空,nickname 的长度最多15个字符,以及我在手机号上添加了一个自定义注解,在确保其符合手机号规范。

    分组校验

    有时,我们的一个实体类可能会在多种情况下使用,而又不想每种情况都定义一个实体类,则可以采用分组校验的方式,在不同的情况下,采用不同的校验方案。


    首先自定义几种不同情况下的接口:

    public interface Create {
    }
    
    public interface Update {
    }
    


    然后在指定的 pojo 上指定不同的情况下的策略:

    @Data
    public class Demo {
        @Size(max = 15, groups = Create.class)
        @Size(max = 10, groups = Update.class)
        private String name;
        
        @Max(value = 100, groups = Create.class)
        @Max(value = 20, groups = Update.class)
        private Integer age;
    }
    


    最后,在不同的方法上,根绝业务需要指定使用不同的策略即可:

        @PostMapping("xss3")
        public String xssPost(@Validated({Create.class}) @RequestBody Demo xss3) {
            return JSON.toJSONString(xss3);
        }
    
        @PutMapping("xss4")
        public String xssUpdate(@Validated({Update.class}) @RequestBody Demo xss4) {
           return JSON.toJSONString(xss4);
        }
    

    在这种情况下,则在执行 xssPost() 方法时,采用是 Create 的执行方案,在执行 xssUpdate() 方法时,采用的是 Update 方案。

    提供的全部注解

    JSR提供的校验注解:
    @Null 必须为 null
    @NotNull 必须不为 null
    @AssertTrue 必须为 true
    @AssertFalse 必须为 false
    @Min(value) 大于等于 给定数字
    @Max(value) 小于等于 给定数字
    @DecimalMin(value) 大于等于 给定数值
    @DecimalMax(value) 小于等于 给定数字
    @Size(max=, min=) 集合或字符串长度在指定范围内
    @Digits 指定整数部分和小数部分可以接受的最大位数
    @Past 必须为一个过去的时间
    @Future 必须为一个未来的时间
    @Pattern(regex=,flag=) 给定字符串符合正则表达式
    Hibernate Validator提供的校验注解
    @NotBlank(message =) 非 null,且长度必须大于 0
    @Email 符合电子邮箱规范
    @Length(min=,max=) 字符串长度在给定范围内
    @NotEmpty 字符串或集合 非空
    @Range(min=,max=,message=) 数字或字符串表示的数字在指定范围内

    自定义

    当业务需要一些官方没有提供的校验类型的话,为了方便,我们就需要考虑使用自定义注解的形式了。


    这里,我们采用手机号的形式来演示一下,首先我们自定义一个注解:

    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Constraint(validatedBy = {PhoneValidation.class})
    public @interface PhoneValidationAnnotation {
        String message() default "手机号不符合规范格式";
    }
    


    在代码中,我们定义了默认的错误提示信息。


    然后,我们写一个实现类,来具体实现注解所要表达的含义:

    public class PhoneValidation implements ConstraintValidator<PhoneValidationAnnotation, String> {
        String phonePattern;
        Pattern compile;
    
    
        @Override
        public void initialize(PhoneValidationAnnotation constraintAnnotation) {
            phonePattern = "1[3456789]\d{9}";
            compile = Pattern.compile(phonePattern);
        }
    
        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
            return compile.matcher(value).matches();
        }
    }
    

    在代码中,我们创建了一个类,实现 ConstraintValidator 接口,并重写其的初始化方法和验证方法,这样,在验证参数的时候,其就会自动调用相关的方法来验证传递的是否正确。

    // 注解:要校验的数字在给定的集合中
    
    // 定义接口
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Constraint(validatedBy = {EnumValidation.class})
    public @interface EnumValidationAnnotation {
        long[] limitValue() default {};
    }
    
    // 具体实现
    public class EnumValidation implements ConstraintValidator<EnumValidationAnnotation, Long> {
    
        private long[] longValues;
    
        @Override
        public void initialize(EnumValidationAnnotation constraintAnnotation) {
            longValues = constraintAnnotation.limitValue();
        }
    
        @Override
        public boolean isValid(Long value, ConstraintValidatorContext context) {
            for (long longValue : longValues) {
                if (value == longValue) {
                    return true;
                }
            }
            return false;
        }
    }
    
  • 相关阅读:
    OCS 2007 R2单机测试虚拟环境的搭建(windows server 2008 R2 x64)
    Linq的概念解析
    WCF Data Service与net.tcp承载分析
    codeplex上20个有意思的WPF程序
    各种SmartPhone上的跨平台开源框架的总结
    新开发Apple Store上软件的实施步骤
    VSTO应用程序中加入键盘钩子
    绝非偶然 苹果iPhone领先5年背后的迷思 【推荐】
    Windows上安装Mac OS虚拟机
    Visual Studio 远程调试的步骤
  • 原文地址:https://www.cnblogs.com/JRookie/p/13601520.html
Copyright © 2020-2023  润新知