Controller層方法,進行統一異常處理
提供兩種不同的方案,如下:
- 方案1:使用 @@ControllerAdvice (或@RestControllerAdvice), @ExceptionHandler 注解實現;
- 方案2: 使用AOP技術實現;
現在分別介紹
方案1: 使用@ControllerAdvice 和 @ExceptionHandler
@ControllerAdvice 或 @RestControllerAdvice
使用@ControllerAdvice
注解來增強所有的 @RequestMapping
標記的方法;
官方解釋:
It is typically used to define @ExceptionHandler
,@InitBinder
, and @ModelAttribute
methods that apply to all @RequestMapping
methods.
@ExceptionHandler
- 只能聲明方法;
- 與
@ControllerAdvice
結合使用,可以用於增強所有@RequestMapping
方法的異常處理;
核心代碼
完整代碼請參考: Springboot對Controller層方法進行統一異常處理
@RestControllerAdvice
public class ControllerExceptionHandleAdvice {
private final static Logger logger = LoggerFactory.getLogger(ControllerExceptionHandleAdvice.class);
@ExceptionHandler
public ResultEntity handler(HttpServletRequest req, HttpServletResponse res, Exception e) {
logger.info("Restful Http請求發生異常...");
if (res.getStatus() == HttpStatus.BAD_REQUEST.value()) {
logger.info("修改返回狀態值為200");
res.setStatus(HttpStatus.OK.value());
}
if (e instanceof NullPointerException) {
logger.error("代碼00:" + e.getMessage(), e);
return ResultEntity.fail("發生空指針異常");
} else if (e instanceof IllegalArgumentException) {
logger.error("代碼01:" + e.getMessage(), e);
return ResultEntity.fail("請求參數類型不匹配");
} else if (e instanceof SQLException) {
logger.error("代碼02:" + e.getMessage(), e);
return ResultEntity.fail("數據庫訪問異常");
} else {
logger.error("代碼99:" + e.getMessage(), e);
return ResultEntity.fail("服務器代碼發生異常,請聯系管理員");
}
}
}
方案2:使用AOP技術
完整代碼: 【AOP】Springboot對Controller層方法進行統一異常處理
核心代碼
- @Aspect 注解;
- 織入點:
- 方法返回值為:ResultEntity
- 所有帶有controller層級的包 下面的 所有類的所有方法
- @Around("execution(public com.ssslinppp.model.ResultEntity com...controller...*(..))")
@Component
@Aspect
public class ControllerAspect {
public static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
@Around("execution(public com.ssslinppp.model.ResultEntity com..*.controller..*.*(..))")
public Object handleControllerMethod(ProceedingJoinPoint pjp) {
Stopwatch stopwatch = Stopwatch.createStarted();
ResultEntity<?> resultEntity;
try {
logger.info("執行Controller開始: " + pjp.getSignature() + " 參數:" + Lists.newArrayList(pjp.getArgs()).toString());
resultEntity = (ResultEntity<?>) pjp.proceed(pjp.getArgs());
logger.info("執行Controller結束: " + pjp.getSignature() + ", 返回值:" + resultEntity.toString());
logger.info("耗時:" + stopwatch.stop().elapsed(TimeUnit.MILLISECONDS) + "(毫秒).");
} catch (Throwable throwable) {
resultEntity = handlerException(pjp, throwable);
}
return resultEntity;
}
private ResultEntity<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
ResultEntity<?> resultEntity = null;
if (e instanceof RuntimeException) {
logger.error("RuntimeException{方法:" + pjp.getSignature() + ", 參數:" + pjp.getArgs() + ",異常:" + e.getMessage() + "}", e);
resultEntity = ResultEntity.fail(e.getMessage());
} else {
logger.error("異常{方法:" + pjp.getSignature() + ", 參數:" + pjp.getArgs() + ",異常:" + e.getMessage() + "}", e);
resultEntity = ResultEntity.fail(e.getMessage());
}
return resultEntity;
}
}