思路:
为什么要做统一异常处理?
因为异常如果不处理不会以规定的返回格式返回给前端, 所以需要确定返回格式.
如果不用统一异常处理, 就要每个异常都手动捕获, 比如你使用org.springframework.validation的参数校验.你要想按照同一返回捕获异常就需要使用BindingResult
在Controller中的参数中用BindingResult
然后在方法中这样写:
@RequestMapping("/save")
public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
if (result.hasErrors()) {
Map<String, String> map = new HashMap<>();
//1. 获取校验的错误结果
result.getFieldErrors().forEach((item) -> {
String message = item.getDefaultMessage();
String field = item.getField();
map.put(field, message);
});
return R.error(400, "提交的数据不合法").put("data", map);
} else {
brandService.save(brand);
}
brandService.save(brand);
return R.ok();
}
这样看起来比较麻烦.
更好的解决办法还是统一异常处理.
步骤很简单:
- 自定义一个类, 使用@RestControllerAdvice(basePackages = “对controller包中的所有”)
- 然后在这个类中写不同的方法处理不同的异常, 上面使用@ExceptionHandler注解
最好在自定义一个枚举类型报错异常的错误信息和错误码, 以便于前端合作制定规范.
@Slf4j
@RestControllerAdvice(basePackages = "com.haozhancc.gulimall.product.controller")
public class GulimallExceptionControllerAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleVaildException(MethodArgumentNotValidException e) {
log.error("数据校验出现问题{}, 异常类型: {}", e.getMessage(), e.getClass());
BindingResult bindingResult = e.getBindingResult();
Map<String, String> errorMap = new HashMap<>();
bindingResult.getFieldErrors().forEach((fieldError -> {
errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
}));
return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(), BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data", errorMap);
}
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable throwable) {
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(), BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
}
}