怎么让Spring@ControllerAdise与其他定制的Spring@Aspects一起工作?

本教程将介绍如何让Spring@ControllerAdise与其他定制的Spring@Aspects一起工作?的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。

问题描述

我有一个使用@Aspect的自定义记录器,我希望它总是在最后运行,这样无论控制器返回什么响应,它都会被记录到数据库中(所以我在这个方面放了一个@Order(1))。我还使用@ControllerAdvice编写了一个错误处理程序,它使用自定义响应正文处理所有意外异常和返回500,并且我希望记录器也记录这一点,因此我在其上放置了@Order(2),然而,放置@Order注释看起来并不安排Spring方面和Spring ControllerAdility之间的顺序,那么我怎么让错误处理程序始终在记录器之前运行?(当然,不需要将我的错误处理程序转到另一个Spring方面)

推荐答案

我一直在寻找并调试您的主要问题。我没有找到你关于@Order的问题的答案,但我会与你分享我的想法(本文的第二部分)

您是否考虑过使用Interceptor

它们提供了在您进入控制器之前和@ControllerAdvice执行之后(如果有)记录操作的方法。

@Component
public class WebInterceptor extends HandlerInterceptorAdapter {

 private Logger logger = LoggerFactory.getLogger(WebInterceptor.class);

 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  logger.error("WebInterceptor prehandle is now logged");
  return super.preHandle(request, response, handler);
 }

 @Override
 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  logger.error("WebInterceptor after completion is now logged");
  super.afterCompletion(request, response, handler, ex);
 }
}

要激活此侦听器,您需要创建一个新的@Configuration类,实现WebMvcConfigurer

@Configuration
public class AppConfig implements WebMvcConfigurer {

 @Autowired
 private WebInterceptor webInterceptor;

 @Override
 public void addInterceptors(InterceptorRegistry registry) {
  registry.addInterceptor(webInterceptor).addPathPatterns("/user");
 }
}

我已经为测试创建了一个简单的ControllerControllerAdvice

@RestController
public class WebController {
 @GetMapping("/user")
 public String user() {
  throw new IllegalArgumentException("my bad");
 }
}


@RestControllerAdvice
@Order(2)
public class WebAdvice {

 private Logger logger = LoggerFactory.getLogger(WebAdvice.class);

 @ExceptionHandler(RuntimeException.class)
 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
 public void handle(RuntimeException e) {
  logger.error("ControllerAdvice is now logged");
 }
}

结果为:

现在已记录WebAdise句柄
现在已记录完成后的WebInterceptor

如果您需要记录请求,也可以查看以下内容:https://www.baeldung.com/spring-http-logging

以下是我找到的有关Order、Aspect和ControllerAdance的信息

你说得对,@ControllerAdvice@Aspect之间没有优先顺序,嗯……

我不知道为什么(目前还不知道),但当@Aspect指向@Controller方法时,无论您设置的顺序怎么,点切都会在@ControllerAdvice之前执行

@Aspect
@Component
@Order(1)
public class MyAspect {

 private Logger logger = LoggerFactory.getLogger(MyAspect.class);

 @After("execution(* WebController.user(..))")
 public void afterLog() {
  logger.error("Aspect is now logged");
 }
}

@RestControllerAdvice
@Order(2)
public class WebAdvice {

 private Logger logger = LoggerFactory.getLogger(WebAdvice.class);

 @ExceptionHandler(RuntimeException.class)
 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
 public void handle(RuntimeException e) {
  logger.error("ControllerAdvice is now logged");
 }
}

如果Get http://localhost:8080/user,结果将为:

方面现在已记录
ControllerAdise现在已记录

但我发现了一些有趣的事情:如果您设置了一个切入点@After@ControllerAdvice,那么您的方面将在ControlerAdance:

之后执行

@Aspect
@Component
@Order(1)
public class MyAspect {

 private Logger logger = LoggerFactory.getLogger(MyAspect.class);

 @After("execution(* WebAdvice.handle(..)) || execution(* WebController.user(..))")
 public void afterLog() {
  logger.error("Aspect is now logged");
 }
}

它被执行2次。一个在控制器之后,另一个在建议之后。

方面现在已记录
ControllerAdise现在已记录
Aspects现在已记录

也许这可以满足您的需求,但我真的不认为这是一个优雅的解决方案…

仍需解决的事情:

    找到优先于AspectControllerAdvice的方法

希望不管怎样,它都会有所帮助。如果我找到更好的,我会让你知道的。

好了关于怎么让Spring@ControllerAdise与其他定制的Spring@Aspects一起工作?的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。

0
没有账号?注册  忘记密码?