将 GuiceServletContextListener 连接到现有的注入器
wiring up GuiceServletContextListener to an existing injector
我有一个现有的大型 java 程序已经在使用 Guice。我正在尝试添加一个带有 swagger 文档的嵌入式网站。我需要以某种方式将它与 Guice 连接起来,但是当我尝试使用我在主程序中注入的东西时,我尝试的一切都会抛出空指针异常。我想也许我可以通过注射器并以这种方式连接它,使用注射器或创建子注射器。
我已经创建了一个示例应用程序,仅使用使其正常工作所需的代码,其中一个 URL 可以正常工作但不会尝试使用我的主程序中的注入,而另一个确实可以尝试使用注入无效。
我正在尝试做所有这些而不需要 web.xml 通过:
private ContextHandler buildApiContext() {
ResourceConfig resourceConfig = new ResourceConfig();
// Replace EntityBrowser with your resource class
// io.swagger.jaxrs.listing loads up Swagger resources
resourceConfig.packages("web", ApiListingResource.class.getPackage().getName());
//apiServletContainer.reload(resourceConfig);
ServletContainer apiServletContainer = new ServletContainer(resourceConfig);
final ServletContextHandler apiContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
apiContext.setContextPath("/api");
ServletHolder apiBrowser = new ServletHolder(apiServletContainer);
apiContext.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
myGuiceServletContextListener.setMainInjector(blackboard.getMainInjector());
apiContext.addEventListener(myGuiceServletContextListener);
apiContext.addServlet(apiBrowser, "/*");
return apiContext;
}
和
public class MyGuiceServletContextListener extends GuiceServletContextListener {
@Inject private Blackboard blackboard;
@Override
protected Injector getInjector() {
return blackboard.getMainInjector();
}}
我也试过:
return blackboard.getMainInjector().createChildInjector();
在我的主程序中,我开始主程序注入:
Config config = ReadConfig.createConfig();
Injector injector = Guice.createInjector(new Bindings(config));
BigProgramInterface bbInterface = injector.getInstance(BigProgramImpl.class);
bbInterface.start(injector);
绑定看起来像
public class Bindings implements Module {
private Config config;
public Bindings(Config config) {
this.config = config;
}
public void configure(Binder binder) {
Integer fixedThreadPoolSize = 2;
Executor fixedExecutor = Executors.newFixedThreadPool(fixedThreadPoolSize, new FixedThreadFactory());
binder.bind(Executor.class).toInstance(fixedExecutor);
binder.bind(Config.class).toInstance(config);
binder.bind(Blackboard.class).asEagerSingleton();
binder.bind(BigProgramMain.class).asEagerSingleton();
binder.bind(EmbeddedWeb.class).asEagerSingleton();
//binder.bind(MyGuiceServletContextListener.class).asEagerSingleton();
}
黑板注入了,正在获取主注入器,但是不能使用
作品:
@Path("/test")
@Api (value = "/test")
public class TestSwagger {
private static final Logger log = LoggerFactory.getLogger(TestSwagger.class);
@GET
@Path("/get")
@ApiOperation(value = "a working test",
notes = "Returns my test class",
response = MyTest.class,
responseContainer="Class")
@Produces(MediaType.APPLICATION_JSON)
public Response getResult() {
MyTest myTest = new MyTest();
myTest.setMyTestString("this is a test");
return Response.ok().entity(myTest).build();
}}
不工作:
@Path("/testbad")
@Api (value = "/testbad")
public class TestSwaggerBad {
private static final Logger log = LoggerFactory.getLogger(TestSwaggerBad.class);
@Inject private Blackboard blackboard;
@GET
@Path("/get")
@ApiOperation(value = "a non - working test",
notes = "Returns my test class",
response = MyTest.class,
responseContainer="Class")
@Produces(MediaType.APPLICATION_JSON)
public Response getResult() {
MyTest myTest = new MyTest();
myTest.setMyTestString(blackboard.getBigProgramCounter().toString());
return Response.ok().entity(myTest).build();
}}
请查看我的代码以了解具体细节:
https://github.com/phomlish/SwaggerSampleApiWebsite
我仔细查看了您的代码,下面是您如何让它工作:
将 guice 桥添加到您的 pom:
<!-- https://mvnrepository.com/artifact/org.glassfish.hk2/guice-bridge -->
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>guice-bridge</artifactId>
<version>2.5.0-b15</version>
</dependency>
这会将 guice hk2 网桥添加到您的配置中。现在,您需要将其连接起来。为此,我们将创建一个 post 概述的功能:
@Priority(0)
public class GuiceFeature implements Feature {
private Injector i;
public GuiceFeature(Injector i) {
this.i = i;
}
@Override
public boolean configure(FeatureContext context) {
ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(context);
GuiceBridge.getGuiceBridge().initializeGuiceBridge(locator);
GuiceIntoHK2Bridge guiceBridge = locator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(i);
return true;
}
}
请注意,我将您创建的注入器传递给该功能。这很重要,因为您将需要相同的注射器才能找到您的服务。绑定代码相当简单。
最后,您需要注册该功能。在您的 class EmbeddedWeb 中,您添加:
嵌入式网络#buildApiContext:
resourceConfig.register(new GuiceFeature(myGuiceServletContextListener.getInjector()));
同样,我们使用的是您已经创建的同一个注入器。
最后这就是您所需要的,并且您的服务已正确连接。
测试:
artur@pandaadb:~/dev/repo/SwaggerSampleApiWebsite$ curl "http://localhost:8080/api/testbad/get"
{"myTestString":"10"}
希望对您有所帮助,
阿图尔
编辑'''IMPORTANT''':
对于注入,不能使用guice注解。 Jersey 似乎无法识别它们(可能是因为它们不想添加 guice 依赖项)。幸运的是,guice 可以同时使用 javax 和 guice 注释。因此,在您的 TestSwaggerBad class 中,您还需要将导入更改为标准 javax 注释。
我有一个现有的大型 java 程序已经在使用 Guice。我正在尝试添加一个带有 swagger 文档的嵌入式网站。我需要以某种方式将它与 Guice 连接起来,但是当我尝试使用我在主程序中注入的东西时,我尝试的一切都会抛出空指针异常。我想也许我可以通过注射器并以这种方式连接它,使用注射器或创建子注射器。
我已经创建了一个示例应用程序,仅使用使其正常工作所需的代码,其中一个 URL 可以正常工作但不会尝试使用我的主程序中的注入,而另一个确实可以尝试使用注入无效。
我正在尝试做所有这些而不需要 web.xml 通过:
private ContextHandler buildApiContext() {
ResourceConfig resourceConfig = new ResourceConfig();
// Replace EntityBrowser with your resource class
// io.swagger.jaxrs.listing loads up Swagger resources
resourceConfig.packages("web", ApiListingResource.class.getPackage().getName());
//apiServletContainer.reload(resourceConfig);
ServletContainer apiServletContainer = new ServletContainer(resourceConfig);
final ServletContextHandler apiContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
apiContext.setContextPath("/api");
ServletHolder apiBrowser = new ServletHolder(apiServletContainer);
apiContext.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
myGuiceServletContextListener.setMainInjector(blackboard.getMainInjector());
apiContext.addEventListener(myGuiceServletContextListener);
apiContext.addServlet(apiBrowser, "/*");
return apiContext;
}
和
public class MyGuiceServletContextListener extends GuiceServletContextListener {
@Inject private Blackboard blackboard;
@Override
protected Injector getInjector() {
return blackboard.getMainInjector();
}}
我也试过:
return blackboard.getMainInjector().createChildInjector();
在我的主程序中,我开始主程序注入:
Config config = ReadConfig.createConfig();
Injector injector = Guice.createInjector(new Bindings(config));
BigProgramInterface bbInterface = injector.getInstance(BigProgramImpl.class);
bbInterface.start(injector);
绑定看起来像
public class Bindings implements Module {
private Config config;
public Bindings(Config config) {
this.config = config;
}
public void configure(Binder binder) {
Integer fixedThreadPoolSize = 2;
Executor fixedExecutor = Executors.newFixedThreadPool(fixedThreadPoolSize, new FixedThreadFactory());
binder.bind(Executor.class).toInstance(fixedExecutor);
binder.bind(Config.class).toInstance(config);
binder.bind(Blackboard.class).asEagerSingleton();
binder.bind(BigProgramMain.class).asEagerSingleton();
binder.bind(EmbeddedWeb.class).asEagerSingleton();
//binder.bind(MyGuiceServletContextListener.class).asEagerSingleton();
}
黑板注入了,正在获取主注入器,但是不能使用
作品:
@Path("/test")
@Api (value = "/test")
public class TestSwagger {
private static final Logger log = LoggerFactory.getLogger(TestSwagger.class);
@GET
@Path("/get")
@ApiOperation(value = "a working test",
notes = "Returns my test class",
response = MyTest.class,
responseContainer="Class")
@Produces(MediaType.APPLICATION_JSON)
public Response getResult() {
MyTest myTest = new MyTest();
myTest.setMyTestString("this is a test");
return Response.ok().entity(myTest).build();
}}
不工作:
@Path("/testbad")
@Api (value = "/testbad")
public class TestSwaggerBad {
private static final Logger log = LoggerFactory.getLogger(TestSwaggerBad.class);
@Inject private Blackboard blackboard;
@GET
@Path("/get")
@ApiOperation(value = "a non - working test",
notes = "Returns my test class",
response = MyTest.class,
responseContainer="Class")
@Produces(MediaType.APPLICATION_JSON)
public Response getResult() {
MyTest myTest = new MyTest();
myTest.setMyTestString(blackboard.getBigProgramCounter().toString());
return Response.ok().entity(myTest).build();
}}
请查看我的代码以了解具体细节: https://github.com/phomlish/SwaggerSampleApiWebsite
我仔细查看了您的代码,下面是您如何让它工作:
将 guice 桥添加到您的 pom:
<!-- https://mvnrepository.com/artifact/org.glassfish.hk2/guice-bridge -->
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>guice-bridge</artifactId>
<version>2.5.0-b15</version>
</dependency>
这会将 guice hk2 网桥添加到您的配置中。现在,您需要将其连接起来。为此,我们将创建一个 post 概述的功能:
@Priority(0)
public class GuiceFeature implements Feature {
private Injector i;
public GuiceFeature(Injector i) {
this.i = i;
}
@Override
public boolean configure(FeatureContext context) {
ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(context);
GuiceBridge.getGuiceBridge().initializeGuiceBridge(locator);
GuiceIntoHK2Bridge guiceBridge = locator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(i);
return true;
}
}
请注意,我将您创建的注入器传递给该功能。这很重要,因为您将需要相同的注射器才能找到您的服务。绑定代码相当简单。
最后,您需要注册该功能。在您的 class EmbeddedWeb 中,您添加:
嵌入式网络#buildApiContext:
resourceConfig.register(new GuiceFeature(myGuiceServletContextListener.getInjector()));
同样,我们使用的是您已经创建的同一个注入器。
最后这就是您所需要的,并且您的服务已正确连接。
测试:
artur@pandaadb:~/dev/repo/SwaggerSampleApiWebsite$ curl "http://localhost:8080/api/testbad/get"
{"myTestString":"10"}
希望对您有所帮助,
阿图尔
编辑'''IMPORTANT''':
对于注入,不能使用guice注解。 Jersey 似乎无法识别它们(可能是因为它们不想添加 guice 依赖项)。幸运的是,guice 可以同时使用 javax 和 guice 注释。因此,在您的 TestSwaggerBad class 中,您还需要将导入更改为标准 javax 注释。