5.Validation数据校验
级联校验
级联校验,就是在一个类A中设置的属性类型是另一个类B,我们对类A中的属性设置@NotNull等注解校验时,如果也想同时对类B中属性进行校验
这时就需要级联校验了,如何级联校验,就需要在类A中的属性类型是类B的属性上加上注解@Valid
public class PersonVO {
@Valid
private SchoolVO schoolVO;
}
public class SchoolVO {
@NotBlank
private String name;
}
参数校验
参数校验,在Controller类接口方法属性中如果只是普通参数(不是实体类),我们对属性进行校验如果只是单单加了@NotNull等注解不会生效,
需要在Controller类上加上注解@Validated才会生效。
@RestController
@RequestMapping("/curl-test")
@Validated
public class DemoController {
@PostMapping("/id")
public void testRequestBody(@NotBlank String id) {}
}
@Valid与@Validated区别
- @Valid不能使用分组校验,@Validated可以使用分组校验,
- @Validated是spring提供的注解,@Valid校验规范提供的注解
BindingResult
想要获取注解校验结果(异常信息),可以在参数列表中加上BindingResult bindingResult,通过bindingResult可以获取错误等信息。BindingResult用在实体类校验信息返回结果绑定。
举个例子:
@RestController
@RequestMapping("/binding")
@Slf4j
public class BindingResultController {
@PostMapping("/result")
public RestResult testBindingResult(@RequestBody @Validated Param param) {
log.info("test bindingResult param:{}", JSONObject.toJSONString(param));
System.out.println("请求处理成功");
return RestResult.successResult();
}
}
@Data
public class Param {
@NotBlank(message = "名字不能为空")
private String name;
@NotNull(message = "年龄不能为空")
@Min(value = 18, message = "年龄不能小于18")
@Max(value = 30, message = "年龄不能大于30")
private Integer age;
@NotNull(message = "手机号不能为空")
private String phone;
}
请求结果:
请求结果异常,但是不是正常我们定义的响应格式。我们期望返回结果如下格式:
{
"code": 1,
"success": false,
"errMsg": "年龄不能小于18",
"data": null
}
方式一 添加BindingResult类
第一种方法,我们可以直接在controller中通过BindingResult类,返回校验结果看是否有参数错误。
@RestController
@RequestMapping("/binding")
@Slf4j
public class BindingResultController {
/**
* 添加BindingResult处理校验异常返回结果
*
* @param param
* @param bindingResult
* @return
*/
@PostMapping("/result")
public RestResult testBindingResult(@RequestBody @Validated Param param, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return RestResult.failResult(bindingResult.getFieldError().getDefaultMessage());
}
log.info("test bindingResult param:{}", JSONObject.toJSONString(param));
System.out.println("请求处理成功");
return RestResult.successResult();
}
}
BindingResult:
方式二 统一异常处理
当项目中多处出现参数校验的时候,使用统一异常处理,参数校验错误后,会抛出一个MethodArgumentNotValidException
异常,我们可以捕获这个异常并处理。就不用在每个方法上都写BindingResult和异常判断。
@RestController
@RequestMapping("/binding")
@Slf4j
public class BindingResultController {
@PostMapping("/result")
public RestResult testBindingResult(@RequestBody @Validated Param param) {
log.info("test bindingResult param:{}", JSONObject.toJSONString(param));
System.out.println("请求处理成功");
return RestResult.successResult();
}
}
统一异常处理:
@RestControllerAdvice
public class GlobalExceptionHandle {
/**
* 处理参数校验异常
*
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public RestResult notValidExceptionHandle(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
Objects.requireNonNull(bindingResult.getFieldError());
// 这里错误码可以使用自定义的错误码枚举
return RestResult.failResult(ErrorCodeEnum.ERROR_INCOMPLETE_RESULT.getCode(),
bindingResult.getFieldError().getField() + " " + bindingResult.getFieldError().getDefaultMessage());
}
@ExceptionHandler({BindException.class})
public RestResult MethodArgumentNotValidExceptionHandler(BindException e) {
// 从异常对象中拿到ObjectError对象
ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
return RestResult.failResult(ErrorCodeEnum.ERROR_INCOMPLETE_RESULT.getCode(), objectError.getDefaultMessage());
}
}
错误码枚举类:
public enum ErrorCodeEnum {
SUCCESS(0, "请求成功"),
ERROR(500, "未知异常"),
ERROR_EMPTY_RESULT(1001, "查询结果为空"),
ERROR_INCOMPLETE_RESULT(1002, "请求参数异常");
private int code;
private String message;
ErrorCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
参数校验异常返回结果:
JSR303数据校验
JSR303数据校验 , 这个就是我们可以在字段上增加一层过滤器验证 , 可以保证数据的合法性
spring-boot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。
我们这里来写个注解让我们的name只能支持Email格式:
注意:一定要写@Validated注解后才能使用校验
@Component //注册bean
@ConfigurationProperties(prefix = "person")
@Validated //数据校验
public class Person {
//@Value("${person.name}")
@Email //name必须是邮箱格式
private String name;
}
查看源码:
本文来自博客园,作者:Lz_蚂蚱,转载请注明原文链接:https://www.cnblogs.com/leizia/p/16686856.html