我有许多客户端定义了"全局"请求拦截器。对于其中一个客户端,我需要排除这个"全局"拦截器。是否可以覆盖特定FeignClient的完整请求拦截器集?
@FeignClient(value = "foo", configuration = FooClientConfig.class)
public interface FooClient {
//operations
}
@Configuration
public class FooClientConfig{
//How do I exclude global interceptors from this client configuration?
}
使用的 spring-cloud-netflix 版本是 1.1.0 M5
似乎没有简单的方法来覆盖全局拦截器。我认为你可以这样做:
@Configuration
public class FooClientConfig{
@Bean
RequestInterceptor globalRequestInterceptor() {
return template -> {
if (template.url().equals("/your_specific_url")) {
//don't add global header for the specific url
return;
}
//add header for the rest of requests
template.header(AUTHORIZATION, String.format("Bearer %s", token));
};
}
}
基于此处所述的问题。您需要为每个 API 定义不同的假装客户端,而不是排除拦截器。根据您的需求添加拦截器。
public class ConfigOne {
@Bean
public InterceptorOne interceptorOne(AdditionalDependency ad) {
return new InterceptorOne(ad);
}
}
只要确保你不要在上面的类上使用@Configuration注释。相反,在客户端定义上导入此 Bean 将是一个可行的解决方案。
@FeignClient(name = "clientOne", configuration = ConfigOne.class)
public interface ClientOne { ... }
解决此问题的一种增强方法是将自定义标头传递给您的请求,例如:
@PostMapping("post-path")
ResponseEntity<Void> postRequest(@RequestHeader(HEADER_CLIENT_NAME) String feignClientName, @RequestBody RequestBody requestBody);
我只想为这个假客户端在拦截器中设置标头。在设置标头之前,拦截器首先检查标头是否存在HEADER_CLIENT_NAME并具有所需的值:
private boolean criteriaMatches(RequestTemplate requestTemplate) {
Map<String, Collection<String>> headers = requestTemplate.headers();
return headers.containsKey(HEADER_CLIENT_NAME)
&& headers.get(HEADER_CLIENT_NAME).contains("feign-client-name");
}
因此,您可以在设置基本身份验证之前进行检查。在拦截器中:
@Override
public void apply(RequestTemplate template) {
if (criteriaMatches(template)) {
/*apply auth header*/
}
}
这样,其他假装客户端的请求就不会被此拦截器操纵。
最后,我将 feignClientName 设置为请求:
feignClient.postRequest("feign-client-name", postBody);
一种方法是从FooClientConfig
类中删除@Configuration
注释,因为在当前情况下,它是全局应用的。
然后使用
@FeignClient(value = "foo", configuration = FooClientConfig.class)
在您要与之一起使用配置的所有假客户端上。