Springboot对Controller层方法进行统一异常处理

Posted 南望孤笑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
    }
}

 


以上是关于Springboot对Controller层方法进行统一异常处理的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot中在除Controller层 使用Validation的方式

springboot聚合项目如何对外暴露api

SpringBoot框架中的DAO层Entity层Service层Controller层

基于SpringBoot+MyBatis 五子棋双人对战

Springboot的entity,dao,controller,service层级理解

Springboot中如何优雅的写好controller层代码