Spring-Validation校验参数

Spring-Validation校验参数

全方面使用参数校验工具

//被注释的元素,值必须是一个字符串,不能为null,且调用trim()后,长度必须大于0
@NotBlank(message = "")

//被注释的元素,值不能为null,但可以为"空",用于基本数据类型的非空校验上,而且被其标注的字段可以使用 @size、@Max、@Min 等对字段数值进行大小的控制
@NotNull(message = "")

//被注释的的元素,值不能为null,且长度必须大于0,一般用在集合类上面
@NotEmpty(message = "")

//被注释的元素必须符合指定的正则表达式。
@Pattern(regexp = "", message = "")

//被注释的元素的大小必须在指定的范围内。
@Size(min =, max =)

//被注释的元素,值必须是一个数字,且值必须大于等于指定的最小值
@Min(value = long以内的值, message = "")

//被注释的元素,值必须是一个数字,且值必须小于等于指定的最大值
@Max(value = long以内的值, message = "")

//被注释的元素,值必须是一个数字,其值必须大于等于指定的最小值
@DecimalMin(value = 可以是小数, message = "")

//被注释的元素,值必须是一个数字,其值必须小于等于指定的最大值
@DecimalMax(value = 可以是小数, message = "")

//被注释的元素,值必须为null
@Null(message = "")

//被注释的元素必须是一个数字,其值必须在可接受的范围内
@Digits(integer =, fraction =)

//被注释的元素,值必须为true
@AssertTrue(message = "")

//被注释的元素,值必须为false
@AssertFalse(message = "")

//被注释的元素必须是一个过去的日期
@Past(message = "")

//被注释的元素必须是一个将来的日期
@Future(message = "")

//被注释的元素必须是电子邮件地址
@Email(regexp = "", message = "")
//被注释的元素必须在合适的范围内
@Range(min =, max =, message = "")

//被注释的字符串的大小必须在指定的范围内
@Length(min =, max =, message = "")

引入Maven依赖

代码实现

  • 如果项目的框架是 spring boot 的话,在 spring-boot-starter-web 中已经包含了 Hibernate-validator 的依赖(版本必须是2.3之前)。2.3以后的版本 spring-boot-starter-web已经去除了这个依赖,需要手动引入 Hibernate-validator依赖,详细内容见官网描述

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  • springboot项目的话直接引入

<dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.17.Final</version>
</dependency>

1.简单在方法上校验参数

@Data
public class UserForNormal {
    String id;

    @NotNull
    @Length(min=3,max=8)
    String name;
    @NotNull
    @Email
    String email;

    @Min(value = 18,message = "未满18哟")
    @Max(value = 24,message = "超过24咯")
    Integer age;

}
@Validated
@RestController
@RequestMapping("/v")
public class ValidationController {
//推荐将一个个参数平铺到方法入参中。
// 在这种情况下,必须在 Controller 类上标注 @Validated 注解,
// 并在入参上声明约束注解 (如 @Min 等)。
// 如果校验失败,会抛出 ConstraintViolationException 异常。
    @GetMapping("/1")
    public Object get1(@Length(min=6,max = 10)@NotNull String str,
                       @NotNull String a){
        return str;
    }

    @PostMapping("/2")
    public Object save(@Validated @RequestBody UserForNormal user){

        return "2";
    }
}

2.分组校验对象参数

@Data
public class UserForGroup {

    @Min(value = 10, groups = Update.class)
    String id;

    @NotNull(groups = {Save.class, Update.class})
    @Length(min = 2, max = 10, groups = {Save.class, Update.class})
    String name;

    @NotNull(groups = {Save.class})
    String email;


    public interface Save {
    }
    public interface Update {
    }
}

    /*
    @Validated 注解上指定校验分组
    * */

    @PostMapping("/save")
    public Object saveUser(@RequestBody @Validated(UserForGroup.Save.class) UserForGroup user) {
        // 校验通过,才会执行业务逻辑处理
        return "save";
    }

    @PostMapping("/update")
    public Object updateUser(@RequestBody @Validated(UserForGroup.Update.class) UserForGroup user) {
        // 校验通过,才会执行业务逻辑处理
        return "update";
    }

3.校验对象中嵌套的对象参数值

//实际场景中,有可能某个字段也是一个对象,这种情况先,可以使用嵌套校验。
    //必须标记 @Valid 注解
    @Data
public class UserForObject {

    @Length(min = 2, max = 10)
    private String userName;

    @NotNull
    @Valid
    private Job job;

    @Data
    public static class Job {

        @Length(min = 2, max = 10)
        private String jobName;

    }
}
/*    嵌套校验
    前面的示例中,DTO 类里面的字段都是基本数据类型和 String 类型。
    但是实际场景中,有可能某个字段也是一个对象,这种情况先,可以使用嵌套校验。*/
    @PostMapping("/qiantao")
    public Object customValidator(@RequestBody @Validated UserForObject user) {
        // 校验通过,才会执行业务逻辑处理
/*        {
            "userName":"22",
                "job":
            {
                "jobName":"3"
            }
        }*/
        return "qiantao";
    }

4.开启快速校验模式

当当前校验字段有误,直接返回错误信息,不会校验后面的字段。默认关闭此功能

@Configuration
public class FailFastConfig {

/*    快速失败 (Fail Fast)
    Spring Validation 默认会校验完所有字段,然后才抛出异常。
    可以通过一些简单的配置,开启 Fali Fast 模式,一旦校验失败就立即返回。*/
    @Bean
    public Validator validator(){
        ValidatorFactory validatorFactory= Validation.byProvider(HibernateValidator.class)
                .configure()
                //快速失败模式
        .failFast(true)
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }
}

5.编程式检验参数

    /*
    * 编程式校验
        上面的示例都是基于注解来实现自动校验的,
        在某些情况下,我们可能希望以编程方式调用验证。
        这个时候可以注入 javax.validation.Validator 对象,
        然后再调用其 api。
    *
    * */
    @Autowired
    private javax.validation.Validator globalValidator;

    // 编程式校验
    @PostMapping("/saveWithCodingValidate")
    public Object saveWithCodingValidate(@RequestBody UserForGroup userDTO) {
        Set<ConstraintViolation<UserForGroup>> validate = globalValidator.validate(userDTO, UserForGroup.Save.class);
        // 如果校验通过,validate为空;否则,validate包含未校验通过项
        if (validate.isEmpty()) {
            // 校验通过,才会执行业务逻辑处理

        } else {
            for (ConstraintViolation<UserForGroup> userDTOConstraintViolation : validate) {
                // 校验失败,做其它逻辑
                System.out.println(userDTOConstraintViolation);
            }
        }
        return "编程方式调用验证";
    }

6.自定义校验规则

自定义注解标注需校验参数字段,进行自定义方法校验参数值

注解

@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {IsUniqueIdValidator.class})
public @interface IsUniqueId {
    //默认错误信息提示
    String message() default "非独特id";
    //分组
    Class<?>[] groups() default {};

    //负载
    Class<? extends Payload>[] payload() default {};
}

校验方法

public class IsUniqueIdValidator implements ConstraintValidator<IsUniqueId,String>
{

    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {

        if(value!=null){

            return true;
        }
        return false;
    }
}

校验对象

@Data
public class UserForCustAnnotation {

    @IsUniqueId
    String id;
}

校验测试

    @PostMapping("/custom/val")
    public Object customValidator(@RequestBody @Validated UserForCustAnnotation user) {
        // 校验通过,才会执行业务逻辑处理
        return "custom/annotation";
    }

7.自定义异常处理器处理校验异常

@RestControllerAdvice
public class CommonExceptionHandler {


    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.OK)
    public Map<String,Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex){

        Map map=new HashMap<String,Object>();
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder sb = new StringBuilder("校验失败:");
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            sb.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage()).append(", ");
        }
        String msg = sb.toString();

        map.put("code",5001);
        map.put("msg",msg);
        return map;
    }
    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseStatus(HttpStatus.OK)
    public Map<String,Object> handleConstraintViolationException(ConstraintViolationException ex) {
        Map map=new HashMap<String,Object>();
        Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
        Iterator<ConstraintViolation<?>> iterator = violations.iterator();
        StringBuilder sb = new StringBuilder("校验失败:");
        while (iterator.hasNext()){
            ConstraintViolation<?> next = iterator.next();
            sb.append(next.getPropertyPath().toString().split("\\.")[1]).append(":").append(next.getMessage()).append(", ");
        }


        map.put("code",5001);
        map.put("msg",sb.toString());
        return map;
    }

}

8.@Valid和@Validated

区别@Valid@Validated
提供者JSR-303规范Spring
是否支持分组不支持支持
标注位置Method,filed,constructor,parameter,type_usetype,method,parameter
嵌套校验支持不支持
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值