我一直在寻找和调试您的主要问题。我没有找到你的问题的答案@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
and 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");
}
}
结果是:
WebAdvice 句柄现已记录
WebInterceptor 完成后现在已记录
如果您需要记录请求,您也可以查看此内容:https://www.baeldung.com/spring-http-logging https://www.baeldung.com/spring-http-logging
这是我发现的有关 Order、Aspect 和 ControllerAdvice 的内容
你是对的,之间没有优先级@ControllerAdvice
and a @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");
}
}
If you Get http://localhost:8080/user
结果将是:
方面现已记录
ControllerAdvice 现已记录
但我发现了一些有趣的事情:如果你设置了切入点@After
the @ControllerAdvice
那么你可以在controllerAdvice之后执行方面:
@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次。一份在控制器之后,一份在建议之后。
方面现已记录
ControllerAdvice 现已记录
方面现已记录
也许这可以满足您的需求,但我真的不认为这是一个优雅的解决方案......
还需要解决的事情:
- 找到一种方法来获得优先权
Aspect
and ControllerAdvice
无论如何希望它有帮助。如果我找到更好的东西,我会告诉你。