Java Guice-Jersey-Servlet绑定

Java Guice-Jersey-Servlet绑定,java,servlets,jersey,guice,Java,Servlets,Jersey,Guice,我最近切换到两阶段注入,这在我的servlet绑定中产生了一个错误。我目前正在两种错误模式之间切换,不确定哪个方向是最好的 我遇到的第一个错误是: com.sun.jersey.api.container.ContainerException:资源配置 实例不包含任何根资源类 我的servlet模块如下所示: public class MyServletModule extends JerseyServletModule { @Override protected void co

我最近切换到两阶段注入,这在我的servlet绑定中产生了一个错误。我目前正在两种错误模式之间切换,不确定哪个方向是最好的

我遇到的第一个错误是:

com.sun.jersey.api.container.ContainerException:资源配置 实例不包含任何根资源类

我的servlet模块如下所示:

public class MyServletModule extends JerseyServletModule {
    @Override
    protected void configureServlets() {
        bind(MyServlet.class).asEagerSingleton();

        serve("/*").with(GuiceContainer.class);
    }
}
我可以通过显式提供com.sun.jersey.config.property.packages参数来删除此错误

public class MyServletModule extends JerseyServletModule {

    @Override
    protected void configureServlets() {
        bind(MyServlet.class).asEagerSingleton();

        Map<String,String> parameters = new HashMap<String, String>();
        parameters.put(PackagesResourceConfig.PROPERTY_PACKAGES, MyServlet.class.getPackage().getName());
        serve("/*").with(GuiceContainer.class, parameters);
    }
}
公共类MyServletModule扩展了JerseyServletModule{
@凌驾
受保护的void configureServlets(){
bind(MyServlet.class).asEagerSingleton();
映射参数=新的HashMap();
parameters.put(PackagesResourceConfig.PROPERTY_PACKAGES,MyServlet.class.getPackage().getName());
使用(GuiceContainer.class,参数)服务(“/*”);
}
}
但当我这样做时,Guice会尝试一个不尊重servlet构造函数上@Inject的即时绑定

com.google.inject.ConfigurationException:Guice配置错误:

1) 无法为MyServlet创建绑定。它已经配置好了 在一个或多个儿童喷油器或专用模块上 绑定到MyServletModule.configureServlets(MyServletModule.java:44),如果 在PrivateModule中,您是否忘记公开绑定?虽然 查找MyServlet

1错误在 com.google.inject.internal.InjectorImpl.getBinding(InjectorImpl.java:150)

我的servlet有一个@Inject构造函数,它的参数不能及时绑定。在调试到InjectorImpl之后,我相信这就是我使用PROPERTY_包时失败的原因

我只是不确定使用PROPERTY_包是否正确,我需要修复一些绑定?或者,如果这是错误的方向,我需要以不同的方式修复原始ResourceConfig错误

非常感谢您向正确的方向提供帮助或推动。

Java部分

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.persist.jpa.JpaPersistModule;
import com.google.inject.servlet.GuiceServletContextListener;
import com.sun.jersey.guice.JerseyServletModule;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import com.thjug.apipublic.Echo;

public class ServletContextListener extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {
        final Injector injector = Guice.createInjector(new JerseyServletModule() {
            @Override
            protected void configureServlets() {
                bind(Echo.class);
                bind(ServletContainer.class).in(Singleton.class);
                serve("/*").with(GuiceContainer.class);
            }
        }, new JpaPersistModule("dbUnit"), new LoggingModule());

        injector.getInstance(JPAInitializer.class);
        return injector;
    }
}
web.xml

    <distributable />

    <display-name>API</display-name>

    <filter>
            <filter-name>guiceFilter</filter-name>
            <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
    </filter>
    <filter-mapping>
            <filter-name>guiceFilter</filter-name>
            <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
            <description>Guice Initiate</description>
            <listener-class>com.thjug.base.ServletContextListener</listener-class>
    </listener>

美国石油学会
guiceFilter
com.google.inject.servlet.GuiceFilter
guiceFilter
/*
Guice发起人
com.thjug.base.ServletContextListener
下面是我关于如何使用Guice休息的基调

通过单独绑定资源,我能够将Jersey资源绑定到Guice,而无需使用绑定参数(无需显式提供com.sun.Jersey.config.property.packages参数)

public class BindJerseyResources extends ServletModule {

    @Override
    protected void configureServlets() {
        // excplictly bind GuiceContainer before binding Jersey resources
        // otherwise resource won't be available for GuiceContainer
        // when using two-phased injection
        bind(GuiceContainer.class);

        // bind Jersey resources
        PackagesResourceConfig resourceConfig = new PackagesResourceConfig("jersey.resources.package");
        for (Class<?> resource : resourceConfig.getClasses()) {
            bind(resource);
        }

        // Serve resources with Jerseys GuiceContainer
        serve("/*").with(GuiceContainer.class);
    }
}
也许这有助于避免后一种有问题的绑定



更新了使用两阶段注入的答案。

这里有一篇关于如何进行绑定的文章(包括完整的源代码):

这似乎是在包中识别我的servlet,我得到一个信息级日志,上面写着“info:Root resource classes found:”但后来我仍然得到错误“com.sun.jersey.api.container.ContainerException:ResourceConfig实例不包含任何根资源类。”奇怪,使用
GuiceContainer
时,我没有任何这样的例外。我从上面的代码片段所在的项目中提取了示例。也许这有助于您解决问题(如果问题是由Jersey或Guice的某些版本引起的),例如Github中的示例:这是一个很好的示例,如果我将InitializeGuiceModulesContextListener中的代码转换为使用如下2阶段注入,我可以很容易地重现我的问题:return Guice.createInjector(new BindServicesModule()).createChildInjector(新的BindJersey资源模块());显然,在这种情况下,使用两相注入只是为了演示目的,但实际上我需要它。谢谢,现在我也可以重现错误。问题似乎是提供给
GuiceContainer
的注入器不包含Jersey资源,并且在我看来,提供给
GuiceContainer
的注入器实际上是父注入器(由
Guice.createInjector(new BindServicesModule())
创建的注入器,而不是子注入器),因为在
GuiceModule
中结束的注入器没有父项。David B.实际上在()中解决了这个问题,您需要在绑定资源之前明确地绑定
GuiceContainer
。我更新了,它现在使用两个阶段的注入工作(更改在它自己的分支中)。我也更新了答案。
@Path("/")
@RequestScoped
public class Resource {

    private Storage storage;

    @Inject
    public Resource(Storage storage) {
        this.storage = storage;
    }

    @GET
    @Path("get/{name}")
    @Produces(MediaType.TEXT_PLAIN)
    public String getGuid(@PathParam("name") String name) {
        return storage.get(name);
    }
}