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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步