@Valid只能⽤在controller,@Validated可以⽤在其他被spring管理的类上
@Valid可以加在成员变量上(本⼈⼀般只有在嵌套查询的时候才会使⽤这个注解)
@Validated可以分组
@Valid可以加在成员变量上,所以可以嵌套校验
@RestController
@RequestMapping("/check")
@Validated
publicclass 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
publicclass ParamCheckInService {
public @NotNull(message = "返回值不允许为空") String test(@NotEmpty(message = "s不能为空") String s,String b){
return b;
}
全局异常捕获
BindException
:表单提交有效,对于以json格式提交将会失效MethodArgumentNotValidException
:前端以json格式有效ConstraintViolationException
:参数上加@RequestParam或参数加@NotBlank @NotNull等
@RestControllerAdvice
public class GlodException {
private static final Logger log = LoggerFactory.getLogger(GlodException.class);
/**
* 处理 SpringMVC 参数绑定不正确
* 在全局异常处理里编写
* Validator,valid 校验参数 参数不正确报错处理
* BindException异常针对表单提交有效,对于以json格式提交将会失效
*/
@ExceptionHandler(BindException.class)
public Result<?> bindExceptionHandler(BindException ex) {
log.error(ex.getMessage(),ex);
//单个和全部 任选其一即可
//获取单个错误数据
/* Map<String,Object> restultMap = new HashMap<String,Object>();
FieldError fieldError = ex.getFieldError();
String field = fieldError.getField();
String defaultMessage = fieldError.getDefaultMessage();
String message = restultMap.toString();
return Result.error(500,message);*/
//获取全部错误数据
List<FieldError> fieldErrors = ex.getFieldErrors();
Map<String,Object> restultMap = new HashMap<String,Object>();
for (FieldError fieldError:fieldErrors) {
//获取错误字段
String field = fieldError.getField();
//获取错误信息
String defaultMessage = fieldError.getDefaultMessage();
restultMap.put(field,defaultMessage);
}
String message = restultMap.toString();
return Result.error(500,message);
}
/**
* 处理 SpringMVC 参数绑定不正确
* 在全局异常处理里编写
* Validator,valid 校验参数 参数不正确报错处理
* MethodArgumentNotValidException异常针对前端以json格式有效
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
log.error(ex.getMessage(),ex);
//单个和全部 任选其一即可
//获取单个错误数据
/* Map<String,Object> restultMap = new HashMap<String,Object>();
BindingResult bindingResult = ex.getBindingResult();
FieldError fieldError = bindingResult.getFieldError();
String field = fieldError.getField();
String defaultMessage = fieldError.getDefaultMessage();
String message = restultMap.toString();
return Result.error(500,message);*/
//获取全部错误数据
BindingResult bindingResult = ex.getBindingResult();
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
Map<String,Object> restultMap = new HashMap<String,Object>();
for (FieldError fieldError:fieldErrors) {
//获取错误字段
String field = fieldError.getField();
//获取错误信息
String defaultMessage = fieldError.getDefaultMessage();
restultMap.put(field,defaultMessage);
}
String message = restultMap.toString();
return Result.error(500,message);
}
/**
* 处理 SpringMVC 参数绑定不正确
* 在全局异常处理里编写
* Validator,valid 校验参数 参数不正确报错处理
* ConstraintViolationException异常针对参数上加@RequestParam或参数加@NotBlank @NotNull
* 等
*/
@ExceptionHandler(ConstraintViolationException.class)
public Result<?> constraintViolationExceptionHandler(ConstraintViolationException ex) {
log.error(ex.getMessage(),ex);
//获取全部错误数据
Map<String,Object> restultMap = new HashMap<String,Object>();
Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
for(ConstraintViolation<?> constraintViolation : constraintViolations){
//返回值为 路径.参数 例如 query.name 可以通过截取只取参数
//String key = constraintViolation.getPropertyPath().toString().split("\\.") [1]; 只要参数
String key = constraintViolation.getPropertyPath().toString();
String message = constraintViolation.getMessage();
restultMap.put(key,message);
}
String message = restultMap.toString();
return Result.error(500,message);
}
}
分组校验
- 创建分组,分组是一个接口(接口中无方法),同时可以继承其他的组,这里创建一个Selcet和一个Insert,表示查询和新增分组。
public interface Select { } public interface Insert { }
- 创建Person类,添加校验注解及指定分组
@Data public class Person { /** * controller层必须写为@Validated({分组1.class,分组2.class})才能对添加了分组的属性进行校验 * 如果controller层写为@Validated只能对没有添加分组的属性进行校验,并不能对有分组属性和没有分 * 组属性的一起校验 * 即使分组接口继承了Default接口也不行 */ @NotNull(message = "personId不能为null",groups = Select.class) private Integer personId; @NotEmpty(message = "name不能为空",groups = Insert.class) private String name; @NotNull(message = "请输入年龄") @Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100) private Integer age; }
- 创建查询和新增接口,添加@Validated注解,指定分组,可多个。
@GetMapping("/select")
public Object select(@Validated({Select.class}) Person person) {
return person;
}
@GetMapping("/insert")
public Object insert(@Validated(Insert.class) Person person) {
return person;
}