springboot项目看似简单,但在实际企业项目中,需要遵循很多最佳实践才称得上是在企业中“可用”的项目。本文章描述如何在springboot微服务项目中对异常做全局统一处理。
为什么要针对异常做全局处理:
我们可以想象下如果没有针对异常做全局统一处理会怎样:
每个controller对应的业务代码,都要自己处理异常,风格不统一,搞不好还有人处理的有问题。
当强制要求所有人都用统一的风格处理异常时,那么自然而然需要把相同的代码提取出来,做统一处理。
将异常做全局统一处理的好处:
具体业务逻辑的实现,不用考虑异常如何包装并返回给客户端,简化代码
统一在一个地方处理,易于代码维护。
如何实现:
从spring4.3开始,提供一个注解@RestControllerAdvice,顾名思义,该注解表示针对RestController做切面增强,正好用来做我们需要的全局异常处理切面逻辑。另外还需要一个@ExceptionHandler注解配合用来表示在抛出某个异常时由该注解标注的方法来进行异常处理。
以下是核心代码:
@Order(0)
@RestControllerAdvice("com.yourcompanyname.yourappname.module")
public class GlobalExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
*针对业务异常的处理
* @param exception
* @return
* @throws Exception
*/
@ExceptionHandler(BaseException.class)
public JSONResponse baseExceptionHandle(BaseException exception) throws Exception {
String retMessage = exception.getRetMessage();
int retCode = exception.getRetCode();
LOGGER.error("Code {}, Message {}", retCode, retMessage, exception);
return getJSONResult(retCode, retMessage);
}
可以看到定义了一个BaseException类表示业务处理时出现异常,这样所有的业务处理时,如果有需要,只要抛出这个异常即可。另外,这个BaseException是运行期异常,不会要求上层调用方一定要捕获该异常,因为GlobalExceptionHandler已经处理了。
除了自定义的业务异常以外,一般还要在GlobalExceptionHandler中处理Exceptino,作为兜底。参见下面代码:
/**
* 针对其他未指定特定处理逻辑的异常进行处理
* @param exception
* @return
* @throws Exception
*/
@ExceptionHandler(Exception.class)
public JSONResponse exception(Exception exception) throws Exception {
int retCode = ResultCodeEnum.ERROR_SYSTEM.getCode();
String retMessage = ResultCodeEnum.ERROR_SYSTEM.getMessage();
LOGGER.error("Code {}, Message {}", retCode, retMessage, exception);
return getJSONResult(retCode, retMessage);
}