在我们使用springboot作为微服务框架进行敏捷开发的时候,为了保证传递数据的安全性,需要对传递的数据进行校验,但是在以往的开发中,开发人员花费大量的时间在繁琐的if else 等判断语句来对参数进行校验,这种方式不但降低了我们的开发速度,而且写出来的代码中带有很多冗余代码,使得编写的代码不够优雅,为了将参数的验证逻辑和代码的业务逻辑进行解耦,Java给我们提供了@Valid注解,用来帮助我们进行参数的校验,实现了将业务逻辑和参数校验逻辑在一定程度上的解耦,增加了代码的简洁性和可读性。springboot中自带了spring validation参数校验框架,其使用上和@valid差不多,在这里就不累述了,本文主要讲解@valid的使用对其参数校验失败后的错误一样的统一处理。
首先,简介对微服务开发中异常的统一处理,spring中的@RestControllerAdvice注解可以获取带有@controller注解类的异常,通过@ExceptionHandler(MyException.class)注解来共同完成对异常进行处理。示例如下:
/**
* 通用异常拦截处理类(通过切面的方式默认拦截所有的controller异常)
*/
@Slf4j
@RestControllerAdvice
public class CommonExceptionHandler {
/**
* 对运行时异常进行统一异常管理方法
* @param e
* @return
*/
@ExceptionHandler(FlyException.class) // FlyException类继承于RuntimeException
public ResponseEntity<Map<String, Object>> handlerException(FlyException e) {
Map<String, Object> result = new HashMap<>(1);
result.put("message", e.getMessage());
return ResponseEntity.status(e.getCode()).body(result);
}
通过注解@RestControllerAdvice和注解@ExceptionHandler的联合使用来实现对异常的统一处理,然后在前端以友好的方式显示。
使用@Valid注解的示例如下:
@PostMapping
public ResponseEntity save(@Valid BrandCreateRequestDto dto, BindingResult bindingResult) {
// 判断是否含有校验不匹配的参数错误
if (bindingResult.hasErrors()) {
// 获取所有字段参数不匹配的参数集合
List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
Map<String, Object> result = new HashMap<>(fieldErrorList.size());
fieldErrorList.forEach(error -> {
// 将错误参数名称和参数错误原因存于map集合中
result.put(error.getField(), error.getDefaultMessage());
});
return ResponseEntity.status(HttpStatus.BAD_REQUEST.value()).body(result);
}
brandService.save(dto);
return ResponseEntity.status(HttpStatus.CREATED.value()).build();
}
@Valid注解确实将我们原来的参数校验的问题进行了简化,但是,如果我们有多个handler需要处理,那我们岂不是每次都要写这样的冗余代码。通过查看@valid的实现机制(这里就不描述了),当参数校验失败的时候,会抛出MethodArgumentNotValidException异常(当用{@code @Valid}注释的参数在验证失败时,将引发该异常):
/**
* Exception to be thrown when validation on an argument annotated w