我最近切换到两阶段注入,这在我的servlet绑定中创建了一个错误。我目前正在两种错误模式之间切换,不确定哪种方向最适合。
我遇到的第一个错误是:
com.sun.jersey.api.container.ContainerException:ResourceConfig instance不包含任何根资源类。
我的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
1错误 com.google.inject.internal.InjectorImpl.getBinding(InjectorImpl.java:150)
我的servlet有一个@Inject构造函数,它的参数不能及时绑定。在调试InjectorImpl后,我相信当我使用PROPERTY_PACKAGES时,这就是事情失败的原因。
我只是不确定使用PROPERTY_PACKAGES是否正确,我需要修复一些绑定?或者,如果这是错误的方向,我需要以不同的方式修复原始的ResourceConfig错误。
赞赏帮助或推动正确的方向。
答案 0 :(得分:8)
我能够通过单独绑定资源,在不使用bind-parameters(没有显式提供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);
}
}
也许这可以帮助您避免后一个有问题的绑定。
更新了使用两阶段注射的答案。
答案 1 :(得分: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
答案 2 :(得分:0)
这是一篇关于如何进行绑定的文章(包括完整的源代码): implementing-distributed-counter