Я искал и устранял твою главную проблему. Я не нашел ответа на ваш вопрос о @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");
}
}
И результат:
Дескриптор WebAdvice теперь зарегистрирован WebInterceptor после завершения теперь регистрируется
Вы также можете посмотреть это, если вам нужно регистрировать запросы: https://www.baeldung.com/spring-http-logging
Вот что я Вы узнали о Order, Aspect и ControllerAdvice
Вы правы, между @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
результат будет:
Аспект теперь зарегистрирован ControllerAdvice теперь регистрируется
Но я нашел кое-что интересное: если вы установите pointcut @After
@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
и ControllerAdvice
Надеюсь, это все равно поможет. Если я найду что-нибудь получше, я дам вам знать.