如何排除特定 Spring Cloud Feign 客户端的 RequestInterceptor?

Posted

技术标签:

【中文标题】如何排除特定 Spring Cloud Feign 客户端的 RequestInterceptor?【英文标题】:How to exclude RequestInterceptor for an specific Spring Cloud Feign client? 【发布时间】:2016-07-01 08:11:31 【问题描述】:

我有许多客户已经定义了“全局”RequestInterceptor。对于其中一个客户,我需要排除这个“全局”拦截器。是否可以覆盖特定 FeignClient 的全套 RequestInterceptor?

@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

【问题讨论】:

这是一个有趣的问题。我的第一个猜测是,您可能必须扩展一个 Feign.Builder 以忽略对 requestInterceptors 的任何调用或忽略您想要的那些。 @spencergibb 换句话说,对于给定的客户端,我想使用自定义客户端配置覆盖任何现有的拦截器。这非常困难。 我很难维护我不想包含在此客户端中的拦截器列表。因此,我根本不打算注册全局拦截器。相反,每个客户端都将被声明为附加一个特定的配置。就我而言,这意味着我将拥有 2 种自定义 feign 客户端配置,一种用于大多数客户端,另一种用于特殊/一次性客户端。 :-( 这是因为你可以有多个拦截器,并且 feign 应用程序上下文继承自父级。也许可以选择不从 @FeignClient 上的父级继承? 这是一个很好的解决方法 【参考方案1】:

解决此问题的一种增强方法是将自定义标头传递给您的请求,例如:

@PostMapping("post-path")
ResponseEntity<Void> postRequest(@RequestHeader(HEADER_CLIENT_NAME) String feignClientName, @RequestBody RequestBody requestBody);

我只想为这个 feign 客户端在拦截器中设置标头。在设置标头之前,拦截器首先检查 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*/
    

这样,其他feign客户端的请求就不会被这个拦截器操纵了。

最后,我将 feignClientName 设置为请求:

feignClient.postRequest("feign-client-name", postBody);

【讨论】:

【参考方案2】:

似乎没有简单的方法可以覆盖全局拦截器。 我认为你可以这样做:

@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));
    ;


【讨论】:

以上是关于如何排除特定 Spring Cloud Feign 客户端的 RequestInterceptor?的主要内容,如果未能解决你的问题,请参考以下文章

如何从使用云侦探的跟踪中排除一些使用 Feign 的调用

spring cloud中如何通过feign调整负载均衡规则

如何使用 spring-cloud-netflix 和 feign 编写集成测试

如何微调 Spring Cloud Feign 客户端?

Spring-Cloud之Feign

如何使用 Spring Cloud 将 Hystrix 属性设置为 Feign 请求?