首页  编辑  

SpringBoot统一异常处理(@ControllerAdvice)后日志中类名不正确问题的解决方法

Tags: /Java/   Date Created:
在SpringBoot中,我们可以统一异常处理,例如使用 @ControllerAdvice 和  @ExceptionHandler
但是这种方式,如果在异常中,我们需要把异常记录到日志当中,会产生一个问题,就是日志中记录的Category 全部变成了 Advice 的类名。
例如:
  1. // Home Controller 中,如果不统一异常的话, log.error 中输出日志的类名是 HomeController,
  2. @Controller
  3. public class HomeController {
  4.     @GetMapping("/")
  5.     public String home(Model model) {
  6.         if (model.getAttribute("name").toString().isEmpty()) throw new RuntimeException("Oops!");
  7.         model.addAttribute("name""Good boy, now: " + Util.now());
  8.         return "home";
  9.     }
  10. }
  11. // 使用 @Advisor 统一异常处理后
  12. package tacos.advisor;
  13. import org.slf4j.Logger;
  14. import org.slf4j.LoggerFactory;
  15. import org.springframework.web.bind.annotation.ControllerAdvice;
  16. import org.springframework.web.bind.annotation.ExceptionHandler;
  17. @ControllerAdvice
  18. public class GlobalExceptionHandler {
  19.     @ExceptionHandler(Exception.class)
  20.     public Object handleException(Throwable exception) {
  21.         log.error("fail: {}", exception);
  22.         return null;
  23.     }
  24. }
统一前的日志:
23:02:04.197 [ERROR] [tacos.controller.HomeController ] fail: {} 
统一后变成了
23:02:04.197 [ERROR] [tacos.controller.GlobalExceptionHandler ] fail: {} 
如何让统一后也继续用异常发生时所在的类名类作为日志类名输出日志呢?
解决方法:
  1. @ControllerAdvice
  2. public class GlobalExceptionHandler {
  3.     @ExceptionHandler(Exception.class)
  4.     public Object handleException(Throwable exception) {
  5.         Logger log = LoggerFactory.getLogger(exception.getStackTrace()[0].getClassName());
  6.         log.error("fail: {}", exception);
  7.         return null;
  8.     }
  9. }
这样日志就和原来一样了。