SpringBoot接口 - 统一异常处理
为什么要统一异常处理
如果不统一处理异常,程序开发时就需要在controller层写大量重复的Valid代码, 比如下面这个样子:
@Slf4j
@RestController
public class Controller {
/**
*
* @param ListReq
* @return
* @throws Exception
*/
@RequestMapping("/list")
public ResponseMessage getList(@Valid @RequestBody ListReq listReq, BindingResult bindingResult) throws Exception {
log.info("start /list,请求参数:{}", JSONObject.toJSONString(listReq));
//参数校验
if (bindingResult.hasErrors()) {
bindingResult.getAllErrors().forEach(objectError -> log.warn("[{}]绑定校验错误[{}]", objectError.getCodes()[0], objectError.getDefaultMessage()));
return ResponseUtil.setFailedResponse(ResponseStatus.PARAM_FAILED);
}
// 参数预处理
try {
// do something
} catch(Exception e) {
return ResponseUtil.setFailedResponse(ResponseStatus.PARAM_FAILED);
}
return ResponseUtil.setSuccessResponse(ResponseStatus.SUCCESS);
}
如上所示,每个接口都会进行重复的参数校验、预处理,最终项目中充斥大量的重复代码,臃肿;那么接下来我们学习使用java提供的@ControllerAdvice统一异常处理简化我们的代码。
@ControllerAdvice异常统一处理
先看代码实现:
异常处理
/**
* 统一处理异常信息
*/
@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {
/**
* 捕获接口请求参数校验异常
*/
@ResponseBody
@ExceptionHandler(value = {BindException.class, ValidationException.class,
MethodArgumentNotValidException.class, MissingServletRequestParameterException.class})
public ResponseMessage handleParameterVerificationException(@NonNull Exception e) {
if (e instanceof MethodArgumentNotValidException) {
//MethodArgumentNotValidException异常:@RequestBody上validate失败后抛出的异常,json格式有效
BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
bindingResult.getAllErrors().forEach(
objectError -> log.warn("[{}]绑定校验错误[{}]", objectError.getCodes()[0], objectError.getDefaultMessage()));
} else if (e instanceof BindException) {
//BindException异常:@RequestBody上validate失败后抛出的异常,表单提交有效
BindingResult bindingResult = ((BindException) e).getBindingResult();
bindingResult.getAllErrors().forEach(
objectError -> log.warn("[{}]绑定校验错误[{}]", objectError.getCodes()[0], objectError.getDefaultMessage()));
} else {
//@RequestParam上validate失败后抛出的异常是javax.validation.ConstraintViolationException异常
//@RequestParam上参数缺失抛出MissingServletRequestParameterException异常
log.warn("绑定校验错误[{}] ", e.getMessage());
}
return ResponseUtil.setFailedResponse(ResponseStatus.PARAM_FAILED);
}
/**
* 捕获其他Exception
*/
@ResponseBody
@ExceptionHandler({Exception.class})
public ResponseMessage customExceptionHandler(Exception e) {
log.error(e.getMessage());
return ResponseUtil.setFailedResponse(ResponseStatus.FAILED);
}
}
接口层(无需特殊处理)
@Slf4j
@Validated
@RestController
public class Controller {
/**
* @param listReq
* @return
* @throws Exception
*/
@RequestMapping("/list")
public ResponseMessage getList(@Valid @RequestBody ListReq listReq) throws Exception {
log.info("start /list,请求参数:{}", JSONObject.toJSONString(listReq));
return confMgmtService.getConfList(confListReq);
}
以上就是统一处理的简单实现~ 快GET起来吧
水滴石穿