当前位置: 首页 > 知识库问答 >
问题:

Spring Cloud Netflix:通过RequestInterceptor将主机请求参数传递给FaignClient

云瑞
2023-03-14

我正在用Eureka、Zuul和FaignClient构建一个Spring云项目(Brixton.M4和Spring Boot 1.3.1),我试图在其中添加多租户支持(租户由子域确定:tenant1.myservice.com)。为了做到这一点,我想通过某种方式将原始子域传递给通过Feign从一个服务转发到另一个服务的请求,但我似乎无法找到正确的方法。

我拥有的是一个客户端,它公开@RestController,调用@FeignClient与我的后端通信,后端通过自己的@RestController向客户端公开服务器操作。

@FeignClient在服务器上使用与我的@RestController相同的接口:

@FeignClient(name = "product")
public interface ProductService extends IProductService {

}

我目前试图做的是在请求拦截器中设置一个标头:

@Component
public class MultiTenancyRequestInterceptor implements RequestInterceptor {

    private CurrentTenantProvider currentTenantProvider;

    @Autowired
    public MultiTenancyRequestInterceptor(CurrentTenantProvider currentTenantProvider) {
        this.currentTenantProvider = currentTenantProvider;
    }

    @Override
    public void apply(RequestTemplate template) {
        try {
            template.header("TENANT", currentTenantProvider.getTenant());
        } catch (Exception e) {
            // "oops"
        }
    }
}

我的提供者类是一个简单的组件,我试图在其中注入一个请求/会话范围bean:

@Component
public class CurrentTenantProvider {

    @Autowired
    private CurrentTenant currentTenant;
    //...
}

bean(我尝试了会话和请求范围):

@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public CurrentTenant currentTenant() {
    return new CurrentTenant();
}

在服务器上,我使用Hibernate多租户提供程序,它应该捕获标头值并使用它来定义要连接到的数据库:

@Autowired
private HttpServletRequest httpRequest;

@Override
public String resolveCurrentTenantIdentifier() {
    return httpRequest.getHeader("TENANT");
}

似乎对服务器的假调用是在另一个线程中完成的,并且超出了传入的请求范围,所以我不确定如何传递该值。

当我在请求拦截器中硬编码租户值时,一切都很好,所以我知道其余的工作正常。

我也看过很多关于Zuul“X-Forwaded-For”头的帖子,但在服务器上收到的请求中找不到它。我也尝试过添加一个ZuulFilter来将主机名传递给下一个请求,但我看到的是,发送给客户端的原始请求是由ZuulFilter接收的,我可以添加,但不能在伪请求发送到后端服务时添加,即使我在zuul中映射它(我想这是有意的?)。

我真的不确定下一步是什么,希望能有一些建议。

共有1个答案

江同化
2023-03-14

希望它对您有任何用处,但我们在SpringCloudSleuth中也做了类似的事情,但我们使用ThreadLocal在不同的库和方法(包括假装的Hystrix)之间传递跨度。

下面是一个突出显示行的示例,其中我们从本地线程检索跨度:https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceFeignClientAutoConfiguration.java#L123

 类似资料:
  • 我正在使用SoundCloud api创建一个应用程序,并尝试附加用户输入的字符串值,但它在界面中显示为null,我如何在url中附加该值? MainActivity.java SCService.java 搜索的字符串在我的SoundCloud.java类 我想在GET参数中附加那个SCURL字符串,但它显示了SCURL的null值,我如何实现这一点? 更新:我如上所述更改了代码,但出现了此错误

  • 是否可以使用UI将项目数组传递到swagger块中的单个参数中?我在ruby\rails应用程序中使用它。请求类型是GET。 我有一个接受许多参数的搜索 API。所有这些都是单一值,但一个设施除外。它接受一个项目数组,并且可以使用类似于下面显示的 URL 进行调用(下面的示例显示了传递的两个值 1 和 2)。 我的参数是这样设置的: 当我在swagger中传递数组作为参数时,EG[1]会生成以下U

  • 问题内容: 这是我的config.json: 这是我的bash命令: 输出: 因此$ PRJNAME是prj1,但是第一次调用仅输出。 有人能帮我吗? 问题答案: 您的示例中的jq程序实际上会尝试查找名为的键。请尝试以下操作:

  • 问题内容: 是否可以将参数传递给filter函数,以便您可以按任何名称进行过滤? 就像是 问题答案: 实际上,还有另一种(也许是更好的解决方案),您可以使用angular的本机“过滤器”过滤器,并且仍将参数传递给自定义过滤器。 考虑以下代码: 要进行此工作,您只需将过滤器定义如下: 如您在这里看到的,weDontLike实际上返回另一个函数,该函数的范围内有您的参数以及来自过滤器的原始项。 我花了

  • 问题内容: 如何通过python模块Requests传递csrftoken?这就是我所拥有的,但是它不起作用,并且我不确定将其传递给哪个参数(数据,标头,身份验证…) 每次都有相同的错误消息。 问题答案: 如果要设置引荐来源标头,则对于该特定站点,您需要将引引来源设置为与登录页面相同的URL: 当使用不安全时,标头通常会被过滤掉,否则无论如何很容易被欺骗,因此大多数站点不再需要设置标头。但是,在使

  • 我通过PowerShell这样调用webservice GET方法: 但是,这给了我以下错误: 和号 CategoryInfo:ParserError:(:)[],ParentContainerErrorRecordException 如果重要的是我的WebAPI代码和路由(该方法有两个必需参数,3个可选参数):