springboot 参数校验 @Validated 以及 @Valid

发布时间 2023-11-06 17:06:15作者: 唏嘘-

1、requestParam参数校验

描述:通常用于get请求或者请求参数比较少的情形。

校验生效的前提:必须在Controller类上标注@Validated注解,在方法或者参数前添加无效!

如果校验失败,会抛出ConstraintViolationException异常。

@GetMapping("/findByNo")
public Result findByNo(@RequestParam @NotBlank(message = "参数不能为空!") String orderNo) throws Exception {
     String str = "请求成功!";
     return new Result(ResultCode.SUCCESS, str);
}

 

2、pathVariable参数校验

描述:通过{}来动态配置请求路径,并将请求路径当成方法的入参之一。

校验生效的前提:必须在Controller类上标注@Validated注解,在方法或者参数前添加无效!

如果校验失败,会抛出ConstraintViolationException异常。

@GetMapping("/findByNo/{orderNo}")
public Result findByNo(@PathVariable @Max(message = "最大值不能超过20!", value = 20) Integer orderNo) throws Exception {
    String str = "请求成功!";
    return new Result(ResultCode.SUCCESS, str);
}

 

3、requestBody参数校验(application/json)

请求方法入参有@RequestBody注解的时候,spring会将它识别成JSON格式的请求,要求调用方必须发送application/json格式的数据;

需要在实体类的字段上添加 约束注解 例如:@NotBlank  ; 在接口参数上使用@Valid和@Validated都可以;

如果校验失败,会抛出MethodArgumentNotValidException异常。

@PostMapping("/save")
public Result saveHmi(@Validated @RequestBody Dev dev) {
      devService.save(dev);
      return new Result(ResultCode.SUCCESS);
}

 

4、表单请求参数校验(application/x-www-form-urlencoded)

当请求方法入参只有实体类接收的时候,spring会将它识别成FORM表单请求,要求调用方必须发送application/x-www-form-urlencoded格式的数据;

需要在实体类的字段上添加 约束注解 例如:@NotBlank  ; 在接口参数上使用@Valid和@Validated都可以;

如果校验失败,会抛出BindException异常。

@PostMapping("/save")
public Result saveHmi(@Validated Dev dev) {
      devService.save(dev);
      return new Result(ResultCode.SUCCESS);
}

 

5、配置:

Spring Validation默认会校验完所有字段,然后才抛出异常。可以通过一些简单的配置,开启Fali Fast模式,一旦校验失败就立即返回。

@Configuration
public class WebParamValidateConfig {
    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                //failFast的意思只要出现校验失败的情况,就立即结束校验,不再进行后续的校验。
                .failFast(true)
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
    }
}

 

6、统一异常处理

@ControllerAdvice是一个增强的 Controller。使用这个 Controller,可以实现三个方面的功能:
全局异常处理
全局数据绑定
全局数据预处理
只拦截Controller,不会拦截Interceptor的异常

@RestControllerAdvice(basePackages = "xxx.xxx.xxx.controller")
public class GlobalExceptionHandler {

    //处理@RequestBody 参数校验
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result methodArgumentNotValidException(MethodArgumentNotValidException e) {
        return new Result(false, ResultCode.FAIL.code(), e.getBindingResult().getFieldError().getDefaultMessage(), null);
    }

  //处理@RequestParam 和 @PathVariable 参数校验
    @ExceptionHandler(value = ConstraintViolationException.class)
    public Result methodArgumentNotValidException(ConstraintViolationException e) {
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";"));
        return new Result(false, ResultCode.FAIL.code(), message, null);
    }

  //处理 application/x-www-form-urlencoded 参数校验 @ExceptionHandler(value = BindException.class) public Result methodArgumentNotValidException(BindException e) { String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining()); return new Result(false, ResultCode.FAIL.code(), message, null); }
}

 

7、feign接口校验

在 FeignClient方法中使用@Validated校验传参; 在类上添加 @Validated  在方法参数上添加 @Valid ,必须组合使用

如果校验失败,会抛出ConstraintViolationException异常。

@FeignClient("xxx")
@Validated
public interface UserInviteActFeignClient {
 
    @PostMapping(value = "/saveDev")
    Result saveDev(@RequestBody @Valid Dev dev);

}

 

8、嵌套校验

当入参实体类的某字段也是对象时,这时,需要对该对象里的字段进行校验时,这就牵扯到了:嵌套校验;

此时,入参实体类的对应的字段对象,必须标记@Valid注解。

public class Dev {
   
    //该字段是一个对象
    @Valid
    private DevAttr attr;

}

 

9、集合校验

如果请求体直接传递了json数组给后台,并希望对数组中的每一项都进行参数校验。

public class ValidationList<E> implements List<E> {
    @Delegate
    @Valid
    public List<E> list = new ArrayList<>();

    @Override
    public String toString() {
        return list.toString();
    }
}

 

@PostMapping("/saveList")
public Result saveList(@RequestBody @Validated ValidationList<Dev> devList) {
    return new Result(ResultCode.SUCCESS);
}