简体   繁体   English

泽西岛-如何在Servlet之外使用@Context注释?

[英]Jersey - How to use @Context annotation outside of a servlet?

I am trying to set up a Jersey ClientResponseFilter. 我正在尝试设置Jersey ClientResponseFilter。 It is working fine, but I want to deserialize my request parameters into a String so I can write helpful messages into a log file containing the actual data. 它工作正常,但我想将我的请求参数反序列化为字符串,以便可以将有用的消息写到包含实际数据的日志文件中。

I was thinking about using MessageBodyWorkers for this. 我正在考虑为此使用MessageBodyWorkers。 As this link below says: "In case you need to directly work with JAX-RS entity providers, for example to serialize an entity in your resource method, filter or in a composite entity provider, you would need to perform quite a lot of steps." 如下所示,“如果需要直接与JAX-RS实体提供者合作,例如在资源方法,过滤器或复合实体提供者中序列化实体,则需要执行很多步骤”。

Source: 7.4. 资料来源: 7.4。 Jersey MessageBodyWorkers API 泽西岛MessageBodyWorkers API

This is exactly what I want to prevent. 这正是我要防止的。

So I was thinking about injecting the messagebodyworkers into my filter like this: 所以我在考虑将messagebodyworkers注入到我的过滤器中,如下所示:

package somepackage.client.response;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;

import org.glassfish.jersey.message.MessageBodyWorkers;
import org.slf4j.Logger;

@Provider
public class ResponseFilter implements ClientResponseFilter {

    // TODO: these workers are not injected
    @Context
    private MessageBodyWorkers workers;
    private final Logger logger;

    public ResponseFilter(Logger logger) {
        this.logger = logger;
    }

    @Override
    public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext)
            throws IOException {
        if (responseValid(responseContext)) {
            return;
        }
        logger.error("Error", "Some param");
    }

    private boolean responseValid(ClientResponseContext responseContext) {
        if (responseContext.getStatus() == HttpServletResponse.SC_OK) {
            return true;
        }
        return false;
    }

}

But the reference is always null and remains null. 但是引用始终为空,并且保持为空。 Note that this filter is running in a standalone application, no servlet container is available. 请注意,此过滤器在独立的应用程序中运行,没有servlet容器可用。

Why isn't the annotation working in this case? 为什么在这种情况下注释不起作用? How can I make it work? 我该如何运作? Or if making this approach to work is impossible, how can I work around this? 或者,如果不可能采用这种方法来工作,我该如何解决?

Any suggestions? 有什么建议么?

OK. 好。 Here is the workaround solution for the problem above: we should use @Inject and the HK2 Dependency Injection Kernel 这是上述问题的解决方法:我们应该使用@Inject和HK2依赖注入内核

HK2 Dependency Injection Kernel Link HK2依赖注入内核链接

First we need to make some changes to the filter: 首先,我们需要对过滤器进行一些更改:

package somepackage.client.response;

import java.io.IOException;

import javax.inject.Inject;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;

import org.glassfish.jersey.message.MessageBodyWorkers;
import org.slf4j.Logger;

public class ResponseFilter implements ClientResponseFilter {

    @Inject
    private MessageBodyWorkers workers;
    private Logger logger;

    @Override
    public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext)
            throws IOException {
        if (responseValid(responseContext)) {
            return;
        }
        logger.error("Error", "Some param");
    }

    private boolean responseValid(ClientResponseContext responseContext) {
        if (responseContext.getStatus() == HttpServletResponse.SC_OK) {
            return true;
        }
        return false;
    }

    public void setLogger(Logger logger) {
        this.logger = logger;
    }

}

As you can see the constructor changed, the class uses the default constructor, and the annotation changed to @Inject. 如您所见,构造函数已更改,该类使用默认的构造函数,并且注释已更改为@Inject。 Be aware that there are two @Inject annotations with the same name. 请注意,有两个具有相同名称的@Inject批注。 Make sure you use: javax.inject.Inject. 确保使用:javax.inject.Inject。

Then we need to implement org.glassfish.hk2.utilities.binding.AbstractBinder: 然后,我们需要实现org.glassfish.hk2.utilities.binding.AbstractBinder:

package somepackage.client;

import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.message.MessageBodyWorkers;
import org.glassfish.jersey.message.internal.MessageBodyFactory;

public class Binder extends AbstractBinder {

    @Override
    protected void configure() {
        bind(MessageBodyFactory.class).to(MessageBodyWorkers.class);
    }

}

And finally we should register the filter and our binder in the client: 最后,我们应该在客户端中注册过滤器和绑定器:

...
        client.register(ResponseFilter.class);
        client.register(new SitemapBinder());
...

Then the worker is going to be injected fine. 然后工人将被罚款。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM