文章
问答
冒泡
spring框架中进行参数校验

一、前言
在后端项目中,我们在做接口开发的时候,多多少少的,总会遇到需要做参数校验的情况。不同的框架会有不同的处理方式,这里我们整理下spring框架下的参数校验。

主要的校验器有两种

  • hibernate-validator
  • spring-boot-starter-validation

这两种都是对JSR303的实现,而spring-boot-starter-validation 又是对 hibernate-validator的二次封装。

二、常规使用

@Data
public class Article {
    @NotBlank
    private String title;
}

 

@PostMapping
public void  create(@Validated @RequestBody Article article){
    System.out.println(JSON.toJSONString(article));
}


三、分组校验

@Data
public class Article {

    public interface Create{}
    public interface Update{}

    @NotNull(groups = {Update.class})
    private Long id;

    @NotBlank(groups = {Create.class,Update.class})
    private String title;

    @NotBlank
    private String content;
}

 

@PostMapping
public void  create(@Validated(value = {Article.Create.class}) @RequestBody Article article){
    System.out.println(JSON.toJSONString(article));
}

 

四、嵌套校验
嵌套的属性上要加上@Valid才会生效

@Data
public class Article {
    @NotBlank
    private String title;

    @Valid
    @NotNull
    private Tag tag;
}


五、单个参数的校验
如果参数不是对象,而是一个属性,这个时候需要把 @Validated 加在类上

@Validated
@RestController
@RequestMapping
public class ArticleController {

    @GetMapping(value = "one")
    public void query(
          @Min(value = 10) @RequestParam(value = "age") Integer age
    ){

    }
}


六、自定义校验
注解

@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UserNameConstraintValidator.class)
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
public @interface UserName {
    String message() default "username is invalid";
    Class<?>[] groups() default {};
    int min();
    Class<? extends Payload>[] payload() default { };
}

对应的验证器

public class UserNameConstraintValidator implements ConstraintValidator<UserName, String> {

    private Integer min = 0;

    @Override
    public void initialize(UserName constraintAnnotation) {
       min = constraintAnnotation.min();
    }

    @Override
    public boolean isValid(String o, ConstraintValidatorContext constraintValidatorContext) {
        return StringUtils.hasText(o) && o.length()>min ;
    }
}


只要注解加在属性上即可。

七、全局异常捕获
参数校验失败之后,还需要告知客户端端,参数校验失败,这个时候可以做全局异常捕获来处理

@Slf4j
@ControllerAdvice
@ResponseBody
public class ApiExceptionHandler {

    @ExceptionHandler(value = {MethodArgumentNotValidException.class,BindException.class})
    public ErrorResponse handleMethodArgumentNotValidException(HttpServletResponse response, MethodArgumentNotValidException ex) {
        if (log.isErrorEnabled()) {
            log.error(ex.getMessage(), ex);
        }
        BindingResult result = ex.getBindingResult();
        FieldError error = result.getFieldError();
        String message = error.getDefaultMessage();

        response.setStatus(400);
        return ErrorResponse.builder().code("ARGUMENT_VALIDATION_ERROR").message(message).build();
    }

    @ExceptionHandler(value = {ConstraintViolationException.class})
    public ErrorResponse handleBindException(HttpServletResponse response, ConstraintViolationException ex) {
        if (log.isErrorEnabled()) {
            log.error(ex.getMessage(), ex);
        }

        response.setStatus(400);
        return ErrorResponse.builder().code("BIND_VALIDATION_ERROR").message(ex.getMessage()).build();
    }

}

 

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ErrorResponse {
    private String code;
    private String message;
}


这样一来,参数校验就会方便很多了。

spring

关于作者

落雁沙
非典型码农
获得点赞
文章被阅读