SpringBoot数据校验与优雅处理详解( 二 )
Validator+BindingResult优雅处理默认已经引入相关依赖 。
为实体类定义约束注解/** * 实体类字段加上javax.validation.constraints定义的注解 * @author Summerday */@Data@ToStringpublic class Person {private Integer id;@NotNull@Size(min = 6,max = 12)private String name;@NotNull@Min(20)private Integer age;}
使用@Valid或@Validated注解@Valid和@Validated在Controller层做方法参数校验时功能相近 , 具体区别可以往后面看 。
@RestControllerpublic class ValidateController {@PostMapping("/person")public Map validatePerson(@Validated @RequestBody Person person, BindingResult result) {Map map = new HashMap<>();// 如果有参数校验失败 , 会将错误信息封装成对象组装在BindingResult里if (result.hasErrors()) {List res = new ArrayList<>();result.getFieldErrors().forEach(error -> {String field = error.getField();Object value = http://kandian.youth.cn/index/error.getRejectedValue();String msg = error.getDefaultMessage();res.add(String.format("错误字段 -> %s 错误值 -> %s 原因 -> %s", field, value, msg));});map.put("msg", res);return map;}map.put("msg", "success");System.out.println(person);return map;}}
发送Post请求 , 伪造不合法数据这里使用IDEA提供的HTTP Client工具发送请求 。
POST http://localhost:8081/personContent-Type: application/json{"name": "hyh","age": 10}
响应信息如下:
HTTP/1.1 200 Content-Type: application/jsonTransfer-Encoding: chunkedDate: Sat, 14 Nov 2020 15:58:17 GMTKeep-Alive: timeout=60Connection: keep-alive{"msg": ["错误字段 -> name 错误值 -> hyh 原因 -> 个数必须在6和12之间","错误字段 -> age 错误值 -> 10 原因 -> 最小不能小于20"]}Response code: 200; Time: 393ms; Content length: 92 bytes
Validator + 全局异常处理在接口方法中利用BindingResult处理校验数据过程中的信息是一个可行方案 , 但在接口众多的情况下 , 就显得有些冗余 , 我们可以利用全局异常处理 , 捕捉抛出的MethodArgumentNotValidException异常 , 并进行相应的处理 。
定义全局异常处理@RestControllerAdvicepublic class GlobalExceptionHandler {/*** If the bean validation is failed, it will trigger a MethodArgumentNotValidException.*/@ExceptionHandler(MethodArgumentNotValidException.class)public ResponseEntity
定义接口@RestControllerpublic class ValidateController {@PostMapping("/person")public Map validatePerson(@Valid @RequestBody Person person) {Map map = new HashMap<>();map.put("msg", "success");System.out.println(person);return map;}}
@Validated精确校验到参数字段有时候 , 我们只想校验某个参数字段 , 并不想校验整个pojo对象 , 我们可以利用@Validated精确校验到某个字段 。
定义接口@RestController@Validatedpublic class OnlyParamsController {@GetMapping("/{id}/{name}")public String test(@PathVariable("id") @Min(1) Long id,@PathVariable("name") @Size(min = 5, max = 10) String name) {return "success";}}
发送GET请求 , 伪造不合法信息GET http://localhost:8081/0/hyhContent-Type: application/json
未作任何处理 , 响应结果如下:
{"timestamp": "2020-11-15T15:23:29.734+00:00","status": 500,"error": "Internal Server Error","trace": "javax.validation.ConstraintViolationException: test.id: 最小不能小于1, test.name: 个数必须在5和10之间...省略","message": "test.id: 最小不能小于1, test.name: 个数必须在5和10之间","path": "/0/hyh"}
【SpringBoot数据校验与优雅处理详解】可以看到 , 校验已经生效 , 但状态和响应错误信息不太正确 , 我们可以通过捕获ConstraintViolationException修改状态 。
捕获异常 , 处理结果@ControllerAdvicepublic class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {private static final Logger log = LoggerFactory.getLogger(CustomGlobalExceptionHandler.class);/*** If the @Validated is failed, it will trigger a ConstraintViolationException*/@ExceptionHandler(ConstraintViolationException.class)public void constraintViolationException(ConstraintViolationException ex, HttpServletResponse response) throws IOException {ex.getConstraintViolations().forEach(x -> {String message = x.getMessage();Path propertyPath = x.getPropertyPath();Object invalidValue = http://kandian.youth.cn/index/x.getInvalidValue();log.error("错误字段 -> {} 错误值 -> {} 原因 -> {}", propertyPath, invalidValue, message);});response.sendError(HttpStatus.BAD_REQUEST.value());}}
- 查询|数据太多容易搞混?掌握这几个Excel小技巧,办公思路更清晰
- 黑莓(BB.US)盘前涨逾32%,将与亚马逊开发智能汽车数据平台|美股异动 | US
- 健身房|乐刻韩伟:产业互联网中只做单环节很难让数据发挥大作用
- V2X|V2X:确保未来道路交通数据交换的安全性
- 短视频平台|大数据佐证,抖音带动三千万就业,视频手机将成生产力工具?
- 权属|从数据悖论到权属确认,数据共享进路所在
- 统计|多久才能换一次手机?统计机构数据有点意外
- 发展|大数据解读世界互联网大会·互联网发展论坛!
- 网购|黑色星期五及网购星期一大数据出炉 全球第三方卖家销售额超48亿美元
- Veeam|Veeam让企业数据拥有“第二次生命”