本文介紹了如何讓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");
}
}
我已經為測試創建了一個簡單的Controller
和ControllerAdvice
:
@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現在已記錄
也許這可以滿足您的需求,但我真的不認為這是一個優雅的解決方案…
仍需解決的事情:
找到優先于Aspect
和ControllerAdvice
的方法
希望不管怎樣,它都會有所幫助。如果我找到更好的,我會讓你知道的。
這篇關于如何讓Spring@ControllerAdise與其他定制的Spring@Aspects一起工作?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,