【異常處理】Springboot對Controller層方法進行統一異常處理


Controller層方法,進行統一異常處理

提供兩種不同的方案,如下:

  1. 方案1:使用 @@ControllerAdvice (或@RestControllerAdvice), @ExceptionHandler 注解實現;
  2. 方案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;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM