zoukankan      html  css  js  c++  java
  • 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;
        }
    }
    
  • 相关阅读:
    C# 从服务器下载文件
    不能使用联机NuGet 程序包
    NPOI之Excel——合并单元格、设置样式、输入公式
    jquery hover事件中 fadeIn和fadeOut 效果不能及时停止
    UVA 10519 !! Really Strange !!
    UVA 10359 Tiling
    UVA 10940 Throwing cards away II
    UVA 10079 Pizze Cutting
    UVA 763 Fibinary Numbers
    UVA 10229 Modular Fibonacci
  • 原文地址:https://www.cnblogs.com/JRookie/p/13601520.html
Copyright © 2011-2022 走看看