Reputation: 949
I define an interceptor and register it in a class (annotated with Configuration) which extends WebMvcConfigurerAdapter
; however, I also use some third-party libraries which also define some interceptors. I want my interceptor to be the last one in the interceptor execution chain. It seems there is no way to enforce this. How to define the execution order of interceptor in Spring Boot application?
Upvotes: 20
Views: 27369
Reputation: 73
Maybe you can use @Order on the Configurer like this.
I use springboot3.
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
MdcWebMvcConfigurer mdcWebInterceptor() {
return new MdcWebMvcConfigurer();
}
I read the source code, the reason why this can work is that the WebMvcConfigurers will be applied in ordered
The source code is here
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
...
}
Upvotes: 0
Reputation: 1
All Feign clients become proxies, so there is only one way to change the order of the request interceptors. But you cannot use it, because if you change the proxy to SGLIB, it will not work.
if(bean instanceof YoursFeignClientBean) {
Class<Proxy> superclass = (Class<Proxy>) bean.getClass().getSuperclass();
Field h = superclass.getDeclaredField("h");
h.setAccessible(true);
// its FeignInvocationHandler
InvocationHandler ih = (InvocationHandler) ReflectionUtils.getField(h, bean);
Field dispatch = ih.getClass().getDeclaredField("dispatch");
dispatch.setAccessible(true);
Map<Method, InvocationHandlerFactory.MethodHandler> map =
(Map<Method, InvocationHandlerFactory.MethodHandler>) dispatch.get(ih);
for (Method method : map.keySet()) {
InvocationHandlerFactory.MethodHandler handler = map.get(method);
Field requestInterceptors = handler.getClass().getDeclaredField("requestInterceptors");
requestInterceptors.setAccessible(true);
List<RequestInterceptor> interceptorList = (List<RequestInterceptor>)
ReflectionUtils.getField(requestInterceptors, handler);
RequestInterceptor ri = interceptorList.stream().filter(t -> t.getClass().getName().startsWith(YoursFeignConfig.class.getName())).findFirst().get();
// reorder
interceptorList.remove(ri);
interceptorList.add(ri);
}
Upvotes: 0
Reputation: 839
According to my experience, Interceptors are adding a stack. For this reason you should addRegister above which one you want before calling than other.
Upvotes: -1
Reputation: 305
If we've Multiple Interceptors, Instead of @Order
Annotation we can do as below.
@EnableWebMvc
@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry
.addWebRequestInterceptor(new WebRequestInterceptor() {
//Overrides
}).order(Ordered.HIGHEST_PRECEDENCE);
registry
.addWebRequestInterceptor(new WebRequestInterceptor() {
//Overrides
}).order(Ordered.LOWEST_PRECEDENCE);
}
}
Upvotes: 12