最终我使用了Google Guice,它是一个轻量级的依赖注入框架,能够很好地与Jersey集成。这是我所做的:
首先,在pom.xml文件中添加依赖项:
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-guice</artifactId>
<version>1.12</version>
<scope>compile</scope>
</dependency>
我希望实现一个DAO,作为单例并具备接口:
public interface MySingletonDao
{
}
还有一个具体的实现:
@Singleton
public class ConcreteMySingletonDao implements MySingletonDao
{
// ... methods go here ...
}
像这样装饰资源类:
@Path("/some/path")
@RequestScoped
public class MyResource
{
private final MySingletonDao mySingletonDao;
@Inject
public MyResource(MySingletonDao mySingletonDao)
{
this.mySingletonDao = mySingletonDao;
}
@POST
@Produces("application/json")
public String post() throws Exception
{
}
}
创建了一个将执行绑定的类:
public class GuiceConfig extends GuiceServletContextListener
{
@Override
protected Injector getInjector()
{
return Guice.createInjector(new JerseyServletModule()
{
@Override
protected void configureServlets()
{
bind(MyResource.class);
bind(AnotherResource.class);
bind(MySingletonDao.class).to(ConcreteMySingletonDao.class);
serve("/*").with(GuiceContainer.class);
}
});
}
}
我使用Jetty作为服务器,而不是Glassfish。在我的功能测试中,代码大致如下:
private void startServer() throws Exception
{
this.server = new Server(8080);
ServletContextHandler root =
new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
root.addEventListener(new GuiceConfig());
root.addFilter(GuiceFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
root.addServlet(EmptyServlet.class, "/*");
this.server.start();
}
EmptyServlet
来自 Sunny Gleason 在答案中提供的示例代码,该答案位于以下链接:https://dev59.com/DHE85IYBdhLWcg3wqVb5#3296467 -- 我最初有
root.addServlet(new ServletHolder(new ServletContainer(new PackagesResourceConfig("com.example.resource"))), "/*");
使用这行代码作为替代
root.addServlet(EmptyServlet.class, "/*")
但这导致Jersey尝试执行依赖注入而不是Guice,从而引起了运行时错误。