SpringBoot接口参数统一校验

SpringBoot检验注解

@Null 限制只能为null。

@NotNull 限制必须不为null。

@NotEmpty 只作用于字符串类型,字符串不为空,并且长度不为0。

@NotBlank 只作用于字符串类型,字符串不为空,并且trim()后不为空串。

@AssertFalse 限制必须为false。

@AssertTrue 限制必须为true。

@DecimalMax(value) 限制必须为一个不大于指定值的数字。

@DecimalMin(value) 限制必须为一个不小于指定值的数字。

@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction。

@Future 限制必须是一个将来的日期。

@Past 验证注解的元素值(日期类型)比当前时间早。

@Max(value) 限制必须为一个不大于指定值的数字。

@Min(value) 限制必须为一个不小于指定值的数字。

@Pattern(value) 限制必须符合指定的正则表达式。

@Size(max,min) 限制字符长度必须在min到max之间。

@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式。

注意:

@NotNull 适用于任何类型被注解的元素必须不能与NULL。

@NotEmpty 适用于String Map或者数组不能为Null且长度必须大于0。

@NotBlank 只能用于String上面 不能为null,调用trim()后,长度必须大于0。

单个参数校验

复制

@RestController
@RequestMapping("validator/")
@Validated
public class ValidatorController {
    @GetMapping("/add")
    public String add(@NotNull(message = "address不能为空") String address) {
        return "检验通过";
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

请求:127.0.0.1:8080/validator/add?address=中国。

返回:检验通过。

请求:127.0.0.1:8080/validator/add。

返回:address不能为空。

说明:在进行单个参数校验时,一定要在Controler类上加@Validated注解,否则校验不会生效。

实体类参数校验

实体User类:

复制

public class User {
    @NotBlank(message = "请输入名称")
    @Length(message = "名称不能超过个 {max} 字符", max = 5)
    public String name;

    @NotNull(message = "请输入年龄")
    @Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)
    public Integer age;

    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public Integer getAge() {return age;}
    public void setAge(Integer age) {this.age = age;}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

controller类:

复制

@RestController
@RequestMapping("validator/")
public class ValidatorController {
    @PostMapping("/add")
    public String addUser(@RequestBody @Valid User user, BindingResult bindingResult) {
        //查看所有字段是否验证通过
        if (bindingResult.hasErrors()) {
            //返回第一条错误信息
            return bindingResult.getAllErrors().get(0).getDefaultMessage();
        }
        return "检验通过";
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

执行如下:

说明:如果采用BindingResult方式来存储异常结果,就必须自己来处理异常。即接口中有BindingResult参数,就必须使用要有上方7,8,9行代码进行异常处理,否则程序会正常执行。

统一异常管理

实体User类,同上。controller类如下:

复制

@RequestMapping("validator/")
public class ValidatorController {
    @PostMapping("/add")
    public String addUser(@Valid @RequestBody User user) {
        return "检验通过";
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

执行结果:

这里没有采用BindingResult来存储异常,程序在这里会报错。可以在这个地方增加统一异常管理。通过报错信息可以知道需要对MethodArgumentNotValidException进行管理,代码如下:

复制

@RestControllerAdvice
public class ValidatedExceptionHander {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String MethodArgumentNotValidHandler(MethodArgumentNotValidException exception) {
        String exceptionInfo = exception.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        return exceptionInfo;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

再次执行:

使用spring boot校验器

检验器代码:

复制

@Component
public class ValidatorUtil implements ApplicationContextAware {
    // 通过Spring获得校验器
    private static Validator validator;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext){
        Validator validatorBean = applicationContext.getBean(Validator.class);
        setValidator(validatorBean);
    }

    public static void setValidator(Validator validatorBean){
        if (validatorBean instanceof LocalValidatorFactoryBean) {
            validator = ((LocalValidatorFactoryBean) validatorBean).getValidator();
        } else if (validatorBean instanceof SpringValidatorAdapter) {
            validator = validatorBean.unwrap(Validator.class);
        } else {
            validator = validatorBean;
        }
    }
    
    public static <T> void validate(T object){
        Set<ConstraintViolation<T>> violationSet = validator.validate(object);
        for (ConstraintViolation<T> violation : violationSet) {
            throw new ValidationException(violation.getMessage());
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.

统一异常管理:

复制

@RestControllerAdvice
public class ValidatedExceptionHander {
    @ExceptionHandler(value = ValidationException.class)
    public String ValidationException(ValidationException exception) {
        return exception.getMessage();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

controller类如下:

复制

@RestController
@RequestMapping("validator/")
public class ValidatorController {
    @PostMapping("/add")
    public String addUser(@RequestBody User user) {
        ValidatorUtil.validate(user);
        return "检验通过";
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

执行如下:

说明:这么做的好处是可以自由的对实体进行检验,与以上方式相比较为灵活。

分组校验

同一个实体在不同的操作中的校验方式是不同的,这就要用到分组校验。比如实体User在新增操作时,id是没有的,但是在更新操作时id又必须存在。通过下面例子来讲解一下是如何实现的。

实体user:

复制

public class User {
    @NotNull(message = "id不能为空", groups = {User.UpdateGroup.class})
    @Null(message = "id必须为空", groups = {User.InsertGroup.class})
    public Integer id;

    @NotBlank(message = "请输入名称")
    @Length(message = "名称不能超过个 {max} 字符", max = 5)
    public String name;

    @NotNull(message = "请输入年龄")
    @Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)
    public Integer age;

    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public Integer getAge() {return age;}
    public void setAge(Integer age) {this.age = age;}

    public interface InsertGroup{}
    public interface UpdateGroup{}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

统一异常:

复制

@RestControllerAdvice
public class ValidatedExceptionHander {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String MethodArgumentNotValidHandler(MethodArgumentNotValidException exception) {
        String exceptionInfo = exception.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        return exceptionInfo;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

controller类:

复制

@RestController
@RequestMapping("validator/")
public class ValidatorController {
    @GetMapping("/update")
    public String updateUser(@Validated(User.UpdateGroup.class) @RequestBody User user) {
        return "更新成功";
    }
    @GetMapping("/insert")
    public String insertUser(@Validated(User.InsertGroup.class) @RequestBody User user) {
        return "保存成功";
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

执行如下:

@Validated和@Valid区别

@Validated 对@Valid 进行了二次封装,但在分组、注解位置、嵌套验证等功能上有所不同。

不同点

@Valid

@Validated

来源

是Hibernate validation 的 校验注解

是 Spring Validator 的校验注解,是 Hibernate validation 基础上的增加版

注解位置

用在 构造函数、方法、方法参数 和 成员属性上

用在 类、方法和方法参数上。但不能用于成员属性

嵌套验证

用在级联对象的成员属性上面

不支持

分组

无此功能

提供分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值