泽西岛2筛选器在客户端请求筛选器中使用容器请求上下文 [英] Jersey 2 filter uses Container Request Context in Client Request Filter

查看:103
本文介绍了泽西岛2筛选器在客户端请求筛选器中使用容器请求上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Jersey 2 Web服务,该服务在收到请求后会向另一个Web服务发出另一个请求,以形成对原始请求的响应.因此,当客户端"A"向我的Web服务"B"发出请求时,"B"向"C"发出请求,这是形成对"A"的响应的一部分.

I have a Jersey 2 Web Service that upon receiving a request, makes another request to another web service in order to form the response for the original request. So, when client "A" makes a request to my web service "B", "B" makes a request to "C" as part of forming the response to "A".

A-> B-> C

A->B->C

我想为Jersey 2 Web服务实现一个过滤器,该过滤器实际上是这样做的:

I want to implement a filter for a Jersey 2 web service that essentially does this:

  • 客户端"A"将发送具有以下标头的请求 我的头文件:第一"

  • Client "A" will send a request that has a header like "My-Header:first"

当我的Web服务"B"然后发出客户端请求"C"时,它应该 追加到该标头,因此它发送带有此标头的请求 我的头文件:第一,第二".

When my web service "B" then makes a client request "C", it should append to that header, so it sends a request with this header "My-Header:first,second".

我想将此实现为过滤器,这样我所有的资源都不必重复添加到请求标头的逻辑.

I want to implement this as a filter so all of my resources don't have to duplicate the logic of appending to the request header.

但是,在Jersey 2中,您会获得以下4个过滤条件:

However, in Jersey 2, you get these 4 filters:

  • ContainerRequestFilter-过滤/修改入站请求
  • ContainerResponseFilter-过滤/修改出站响应
  • ClientRequestFilter-过滤/修改出站请求
  • ClientResponseFilter-过滤/修改入站响应

我需要使用入站请求中的标头,对其进行修改,然后将其用于出站请求,因此从本质上讲,我需要既是ContainerRequestFilter又是ClientRequestFilter的东西.我不认为在同一个过滤器中同时实现这两种方法都是可行的,因为您不知道哪个客户端请求映射到哪个容器请求,或者您呢?

I need to use the header from an inbound request, modify it, then use it an outbound request, so essentially I need something that is both a ContainerRequestFilter and a ClientRequestFilter. I don't think implementing both in the same filter will work, as you don't know which Client Request maps to which Container Request, or do you?

推荐答案

我发现了一种不错的方法,它可以不使用ThreadLocalContainerRequestFilterClientRequestFilter之间进行通信.假定响应容器请求而发出的客户端请求将在同一线程上.

I found a nice way to do this that doesn't use ThreadLocal to communicate between the ContainerRequestFilter and the ClientRequestFilter, as you can't assume that client requests made in response to a container request will be on the same thread.

我实现此目标的方法是在ContainerRequestFilterContainerRequestConext对象中设置一个属性.然后,我可以将ContainerRequestContext对象(显式地或通过依赖项注入)传递到我的ClientRequestFilter中.如果使用依赖项注入(如果使用的是Jersey 2,则可能使用的是HK2),那么无需修改任何资源级别逻辑就可以实现所有这些目的.

The way I achieved this is by setting a property in the ContainerRequestConext object in the ContainerRequestFilter. I can then pass the ContainerRequestContext object (either explicity or through dependency injection) into my ClientRequestFilter. If you use dependency injection (if you're using Jersey 2 then you are probably using HK2), then all of this can be achieved without modifying any of your resource level logic.

具有这样的ContainerRequestFilter:

public class RequestIdContainerFilter implements ContainerRequestFilter {

@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
    containerRequestContext.setProperty("property-name", "any-object-you-like");
}

还有一个ClientRequestFilter在其构造函数中采用ContainerRequestContext:

And a ClientRequestFilter that takes a ContainerRequestContext in its constructor:

public class RequestIdClientRequestFilter implements ClientRequestFilter {

    private ContainerRequestContext containerRequestContext;

    public RequestIdClientRequestFilter(ContainerRequestContext containerRequestContext) {
        this.containerRequestContext = containerRequestContext;
    }

    @Override
    public void filter(ClientRequestContext clientRequestContext) throws IOException {
        String value = containerRequestContext.getProperty("property-name");
        clientRequestContext.getHeaders().putSingle("MyHeader", value);
    }
}

然后这只是将它们绑在一起的一种情况.您将需要工厂来创建所需的任何ClientWebTarget:

Then it's just a case of tying this all together. You will need a factory to create any Client or WebTarget that you need:

public class MyWebTargetFactory implements Factory<WebTarget> {

    @Context
    private ContainerRequestContext containerRequestContext;

    @Inject
    public MyWebTargetFactory(ContainerRequestContext containerRequestContext) {
        this.containerRequestContext = containerRequestContext;
    }

    @Override
    public WebTarget provide() {
        Client client = ClientBuilder.newClient();
        client.register(new RequestIdClientRequestFilter(containerRequestContext));
        return client.target("path/to/api");
    }

    @Override
    public void dispose(WebTarget target) {

    }
}

然后注册过滤器,并将工厂绑定到主应用程序ResourceConfig:

Then register the filter and bind your factory on your main application ResourceConfig:

public class MyApplication extends ResourceConfig {

    public MyApplication() {
        register(RequestIdContainerFilter.class);
        register(new AbstractBinder() {
            @Override
            protected void configure() {
                bindFactory(MyWebTargetFactory.class).to(WebTarget.class);
            }
        }
    }
}

这篇关于泽西岛2筛选器在客户端请求筛选器中使用容器请求上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆