专业的JAVA编程教程与资源

网站首页 > java教程 正文

SpringValidation用注解代替代码参数校验解析

temp10 2024-10-19 15:00:55 java教程 8 ℃ 0 评论

Spring Validation

概念

在原先的编码中,我们如果要验证前端传递的参数,一般是在接受到传递过来的参数后,手动在代码中做 if-else 判断,这种编码方式会带来大量冗余代码,十分的不优雅。
因此,推出了用注解的方式,来代替手动判断的方式,让编码更加的简洁。


SpringValidation用注解代替代码参数校验解析

使用方式

引入注解:
一般在

        <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;
    }
}

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表