天天看点

SpirngBoot请求参数验证及@Validated使用方法

分享知识 传递快乐

SpirngBoot升级到2.3之后,hibernate-validator消失,需要手动依赖spring-boot-starter-validation

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>2.4.3</version>
</dependency>      

常用约束说明

  • @Null:元素为null
  • @NotNull:元素不为null
  • @AssertTrue:元素为true
  • @AssertFalse:元素为false
  • @Min(value):数字的值大于等于指定的最小值
  • @Max(value):个数字的值小于等于指定的最大值
  • @DecimalMin(value):大数值大于等于指定的最小值
  • @DecimalMax(value):大数值小于等于指定的最大值
  • @Size(max=,min=):元素的大小在指定的范围内
  • @Digits(integer,fraction):元素是一个数字,其值必须在可接受的范围内
  • @Past:一个过去的日期
  • @Future:一个将来的日期
  • @Pattern(regex=,flag=):指定的正则表达式
  • @URL:必须是一个URL
  • @Email:必须是email格式
  • @NotBlank:字符串不能为空
  • @NotEmpty:集合不能为空
  • @Length:长度必须在指定范围内
  • @Valid:对实体类进行校验

实体参数约束

如果成员是实体,需要带上 @Valid注解;

@RestController
@RequestMapping("/demo")
public class SupportController {

    @Autowired
    private Demo demo;

    @PostMapping(value = "/save")
    public Result save(@Valid @RequestBody UserReq userReq) {

        return demo.save(userReq);
    }
}      

拼接参数约束

需要在控制层的类上加上 @Validated;

@RestController
@RequestMapping("/demo")
@Validated
public class DemoController {

    @Autowired
    private Demo demo;

    @PostMapping(value = "/list")
    public Result list(@NotBlank(message = "userName不能为空") String userName,
                                         @NotBlank(message = "idno不能为空") String idno) {
        return demo.list(roomid, msgtime);
    }


}      

参数嵌套验证

@Data
@ApiModel(value = "User入参")
public class UserReqVO {

    @NotBlank(message = "用户名称不能为空")
    private String userName;

    @Valid
    private List<RolesReqVO> rolesReq;
}      

异常捕获

全局异常捕获,当出现参数校验不合法时捕获异常,并且返回给前端;

@Slf4j
@RestControllerAdvice
public class DefaultExceptionAdvice {

    private Result defHandler(String msg, Exception e) {
        log.error(msg, e);
        return Result.failed(msg);
    }

    /**
     * 捕获方法参数校验异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result constraintViolationExceptionHandler(ConstraintViolationException exception) {
        Set<ConstraintViolation<?>> message = exception.getConstraintViolations();
        HashMap<String, Object> map = new HashMap<>();
        message.stream().forEach(msg -> {
            String path = msg.getPropertyPath().toString();
            String field = path.substring(path.indexOf(".") + 1);
            map.put(field, msg.getMessageTemplate());
        });
        return Result.failed(map.toString());
    }

    /**
     * 校验Body错误拦截处理
     *
     * @param exception 错误信息集合
     * @return 错误信息
     * 返回状态码:500
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result validationBodyException(MethodArgumentNotValidException exception) {
        FieldError error = exception.getBindingResult().getFieldError();
        String field = error.getField();
        String message = String.format("%s:%s", field, error.getDefaultMessage());
        return Result.failed(message);
    }

}      

@validated和@valid不同点

在spring项目中,@validated和@valid功能很类似,都可以在controller层开启数据校验功能。但是@validated和@valid又不尽相同。

有以下不同点:

  • @Validated:提供分组功能,可以在参数验证时,根据不同的分组采用不同的验证机制;可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
  • @Valid:没有分组功能;可以用在方法、构造函数、方法参数和成员属性(字段)上。

@validated的使用注意点

  • @validated和@valid都可以用在controller层的参数前面,但这只能在controller层生效。
  • @validated如果要开启方法验证。注解应该打在类上,而不是方法参数上。
  • @validated不支持嵌套验证。所以jsr303标准的注解修饰的对象只能基本类型和包装类型。其他类型只能做到检测是否为空,对于对象里面的jsr303标准的注解修饰的属性,不支持验证。