简体   繁体   English

Guice没有注入Jersey的资源

[英]Guice don't inject to Jersey's resources

Parsed allover the whole internet, but can't figure out why this happens. 整个互联网解析,但无法弄清楚为什么会发生这种情况。 I've got a simplest possible project (over jersey-quickstart-grizzly2 archetype) with one Jersey resource. 我有一个最简单的项目(通过jersey-quickstart-grizzly2原型)和一个Jersey资源。 I'm using Guice as DI because CDI doesn't want to work with Jersey either. 我正在使用Guice作为DI,因为CDI也不想和Jersey一起工作。 The problem is that Guice can't resolve the class to use when injecting in Jersey's resources. 问题是Guice无法解析在Jersey资源中注入时要使用的类。 It works great outside, but not with Jersey. 它在外面很好用,但不适用于泽西岛。 Here is the Jersey resource: 这是泽西岛资源:

import com.google.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("api")
public class MyResource {

    private Transport transport;

    @Inject
    public void setTransport(Transport transport) {
        this.transport = transport;
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getIt() {
        return transport.encode("Got it!");
    }
}

Transport interface: 传输接口:

public interface Transport {
    String encode(String input);
}

And it's realization: 它的实现:

public class TransportImpl implements Transport {
    @Override
    public String encode(String input) {
        return "before:".concat(input).concat(":after");
    }
}

Following Google's GettingStarted manual, I've inherited AbstractModule and bound my classes like this: 在Google的GettingStarted手册之后,我继承了AbstractModule并将我的类绑定到这样:

public class TransportModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Transport.class).to(TransportImpl.class);
    }
}

I get injector in main() with this, but don't really need it here: 我在main()使用了这个注入器,但是在这里并不需要它:

Injector injector = Guice.createInjector(new TransportModule());

Btw, there's no problem when I try to do smth like this: 顺便说一句,当我尝试像这样做时,没有问题:

Transport transport = injector.getInstance(Transport.class);

Jersey 2 already has a DI framework, HK2 . 泽西2已经有一个DI框架, HK2 You can either use it, or if you want, you can use the HK2/Guice bridge to bride your Guice module with HK2. 您可以使用它,或者如果您愿意,您可以使用HK2 / Guice桥来使用HK2为您的Guice模块添加新娘。

If you want to work with HK2, at the most basic level, it's not much different from the Guice module. 如果你想使用HK2,在最基本的层面上,它与Guice模块没什么不同。 For example, in your current code, you could do this 例如,在您当前的代码中,您可以执行此操作

public class Binder extends AbstractBinder {
    @Override
    public void configurer() {
        bind(TransportImpl.class).to(Transport.class);
    }
}

Then just register the binder with Jersey 然后只需在Jersey上注册活页夹

new ResourceConfig().register(new Binder());

One difference is the the binding declarations. 一个区别是绑定声明。 With Guice, it "bind contract to implementation", while with HK2, it's "bind implementation to contract". 使用Guice,它“将契约与实现绑定”,而对于HK2,它是“将实现绑定到契约”。 You can see it's reversed from the Guice module. 你可以看到它与Guice模块相反。

If you want to bridge Guice and HK2, it's little more complicated. 如果你想搭建Guice和HK2,那就复杂一点了。 You need to understand a little more about HK2. 你需要更多地了解HK2。 Here's an example of how you can get it to work 这是一个如何让它工作的例子

@Priority(1)
public class GuiceFeature implements Feature {

    @Override
    public boolean configure(FeatureContext context) {
        ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(context);
        GuiceBridge.getGuiceBridge().initializeGuiceBridge(locator);
        Injector injector = Guice.createInjector(new TransportModule());
        GuiceIntoHK2Bridge guiceBridge = locator.getService(GuiceIntoHK2Bridge.class);
        guiceBridge.bridgeGuiceInjector(injector);
        return true;
    }
} 

Then register the feature 然后注册该功能

new ResourceConfig().register(new GuiceFeature());

Personally, I would recommend getting familiar with HK2, if you're going to use Jersey. 就个人而言,如果您打算使用泽西岛,我建议您熟悉HK2。

See Also: 也可以看看:


UPDATE UPDATE

Sorry, I forgot to add that to use the Guice Bridge, you need to dependency. 对不起,我忘了添加使用Guice Bridge,你需要依赖。

<dependency>
    <groupId>org.glassfish.hk2</groupId>
    <artifactId>guice-bridge</artifactId>
    <version>2.4.0-b31</version>
</dependency>

Note that this is the dependency that goes with Jersey 2.22.1. 请注意,这是Jersey 2.22.1的依赖关系。 If you are using a different version of HK2, you should make sure to use the same HK2 version that your Jersey version is using. 如果您使用的是不同版本的HK2,则应确保使用与Jersey版本相同的HK2版本。

Yes, in my opinion the answer above is correct. 是的,在我看来,上面的答案是正确的。 A very good way is to bridge Guice to HK2. 一个很好的方法是将Guice连接到HK2。 I am not 100% sure if it neccessary to create a new TransportModule in the code above. 我不是100%确定是否需要在上面的代码中创建一个新的TransportModule。 Indeed Guice registers its injector in the ServletContext with the class name of Injector anyway, so it can be fetched from there: 实际上,Guice在ServletContext中注册了它的注入器,类名为Injector,所以它可以从那里获取:

        register(new ContainerLifecycleListener() {
        public void onStartup(Container container) {
            ServletContainer servletContainer = (ServletContainer)container;
            ServiceLocator serviceLocator = container.getApplicationHandler().getServiceLocator();
            GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
            GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
            Injector injector = (Injector) servletContainer.getServletContext().getAttribute(Injector.class.getName());
            guiceBridge.bridgeGuiceInjector(injector);
        }
        public void onReload(Container container) {
        }
        public void onShutdown(Container container) {
        }       
    });

Beside that it is not trivial how to configure the REST Endpoints in that way, so I wrote detailled blog about that here . 除此之外,如何以这种方式配置REST端点并非易事,所以我在这里写了详细的博客。

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

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