springboot @valid与@validated的参数校验使用总结

好久没在这平台写博客了,最近整理了这东西,先给出总结

//  @Valid只能用在controller,@Validated可以用在其他被spring管理的类上
//  @Valid可以加在成员变量上(本人一般只有在嵌套查询的时候才会使用这个注解)
//  @Validated可以分组
//  @Valid可以加在成员变量上,所以可以嵌套校验
以及我在总结时随便写的类(东西都在代码里,(*^▽^*))
@RestController
@RequestMapping("/check")
@Validated
public class ParamCheckInController {

    @Autowired
    private ParamCheckInService paramCheckInService;

    @PostMapping("/postDemo")
    public Node postDemo(@RequestBody @Validated Node node) {
        return node;
    }
    @GetMapping("/getDemo")
    public Node getDemo(@Validated Node node) {
        paramCheckInService.test("a","b");
        return node;
    }
    @GetMapping("/getDemo2")
    public String getDemo2( @NotEmpty  String s) {
        return s;
    }
    @PostMapping("/groupDemo1")
    public Book groupDemo1(@RequestBody @Validated Book book) {
        return book;
    }
    @PostMapping("/groupDemo2")
    public Book groupDemo2(@RequestBody @Validated({InsertGroup.class,}) Book book) {
        return book;
    }
    @PostMapping("/groupDemo3")
    public Node groupDemo3(@RequestBody @Validated({InsertGroup.class,UpdateGroup.class}) Node node) {//还有啥@Validated分组是有序校验的之类,感觉没啥用
        return node;
    }
}
@Data
class Node implements Serializable {
    @NotBlank(message = "名称不能为空")
    private String name;
    @NotEmpty(groups = UpdateGroup.class,message = "性别不能为空")
    private String sex;
    @NotNull(groups =InsertGroup.class,message = "年龄不能为空")
    @Max(value = 200,message = "age不能大于200")
    private Integer age;
    @Valid      //对下层进行嵌套调用
    @NotEmpty(message = "bookList不能为空")
    private List<Book> bookList;
}
@Data
class Book implements Serializable{
    @NotEmpty(groups = {UpdateGroup.class, Default.class}, message = "更新时id不能为空")
    private String id;
    @NotNull(groups = {InsertGroup.class}, message = "新增时bookName不能为空")
    private String bookName;
}
@Service
@Slf4j
@Validated
public class ParamCheckInService {
    public @NotNull(message = "返回值不允许为空") String test(@NotEmpty(message = "s不能为空") String s,String b){
        return b;
    }
}

上面的类是本人在总结知识点时自己测试的,而且因为要返回给前端,所以还要全局异常捕获,或者在每个方法用BindResult接收。

@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler({MethodArgumentNotValidException.
class,BindException.class}) @ResponseStatus(HttpStatus.OK) @ResponseBody public Result<T> handleMethodArgumentNotValidException(Exception exception) { StringBuilder errorInfo = new StringBuilder(); BindingResult bindingResult=null; if(exception instanceof MethodArgumentNotValidException){ bindingResult= ((MethodArgumentNotValidException)exception).getBindingResult(); } if(exception instanceof BindException){ bindingResult= ((BindException)exception).getBindingResult(); } for(int i = 0; i < bindingResult.getFieldErrors().size(); i++){ if(i > 0){ errorInfo.append(","); } FieldError fieldError = bindingResult.getFieldErrors().get(i); errorInfo.append(fieldError.getField()).append(" :").append(fieldError.getDefaultMessage()); } return Result.error(errorInfo.toString()); } @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseBody public Result<T> handleDefaultException(Exception exception) { return Result.error("其他错误"); } }

还有需要注意的一点是在分组时,接口如果不继承Default的话,有分组校验的接口是必须加上Default.class的否则会使一些校验注解无效

所以我会在分组的接口上继承Default,不然需要分组的参数都要加Default.class看着不舒服~(controller看着简洁就行,嘿嘿~)

public interface UpdateGroup extends Default {
}
public interface InsertGroup extends Default {
}

 

原文地址:https://www.cnblogs.com/whiteme/p/13612652.html