4

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

我遇到的第一个错误是:

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

我的 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);
    }
}

但是当我这样做时,Guice 会尝试一个 Just in Time 绑定,它不尊重我的 servlet 构造函数上的 @Inject。

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

1) 无法为 MyServlet 创建绑定。它已经配置在绑定在 MyServletModule.configureServlets(MyServletModule.java:44) 的一个或多个子注入器或私有模块上 如果它在 PrivateModule 中,您是否忘记公开绑定?定位 MyServlet 时

com.google.inject.internal.InjectorImpl.getBinding(InjectorImpl.java:150) 出现 1 个错误

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

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

帮助或推动正确的方向表示赞赏。

4

3 回答 3

8

通过单独绑定资源,我能够在不使用绑定参数(没有显式提供 com.sun.jersey.config.property.packages 参数)的情况下将 Jersey 资源绑定到 Guice

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);
    }
}

资源如下

@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);
    }
}

也许这可以帮助您避免后一种有问题的绑定。


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

于 2013-09-24T04:50:07.840 回答
0

这是一篇关于如何进行绑定的文章(包括完整的源代码): implementation-distributed-counter

于 2014-10-02T01:57:32.360 回答
0

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>

下面是我关于如何使用 Guice 制作 REST 的主题演讲 http://www.slideshare.net/nuboat/lightweight-javaee

于 2013-09-24T04:10:35.587 回答