如何在嵌入式 Grizzly Jersey 应用程序的主要方法中使用 HK2 注入对象

How to inject object with HK2 in main method in a embedded Grizzly Jersey application

我在使用 Jersey 设计 REST 微服务时遇到了陷阱 22 问题。我正在尝试创建一个带有嵌入式灰熊服务器的应用程序以降低部署复杂性。因此,我有一个创建灰熊服务器的主要方法。我需要在服务器的 bootstrap 过程之前注入一些对象。

我的主图是这样的:

public static void main(String[] args) {
    App app = new App(new MyResourceConfig());
    // Need to inject app here.
    app.init(args);
    app.start();        
}

如何获取 ServiceLocator 单例实例以便注入我的应用程序对象?

我试过:

ServiceLocatorFactory.getInstance()
                     .create("whatever")
                     .inject(app);

但是,我需要将所有 AbstractBinder 绑定到它上面两次(因为我已经在我的 ResourceConfig 中这样做了)。

将所有 AbstractBinder 绑定到您正在创建的 ServiceLocator,然后将该定位器传递给创建工厂方法的 Grizzly 服务器之一。这将是 Jersey 将从中提取所有服务并将它们粘贴到另一个定位器中的父定位器。例如像

ServiceLocator serviceLocator = SLF.getInstance().create(...);
ServiceLocatorUtilities.bind(serviceLocator, new Binder1(), new Binder2());
App app = new App();
serviceLocator.inject(app);
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
        URI.create(BASE_URI),
        resourceConfig, 
        serviceLocator
);

您需要确保您拥有 Jersey-Grizzly 依赖项,而不仅仅是 Grizzly。

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-grizzly2-http</artifactId>
</dependency> 

另请参阅:

注:

如果您尝试使用 GrizzlyWebContainerFactory 创建 Grizzly servlet 容器,则尝试完成上述工作将很困难。没有工厂方法来传递定位器。 Jersey 确实添加了对 属性 ServletProperties.SERVICE_LOCATOR 的支持,但即便如此,属性 值也应该是 ServiceLocator。 grizzly servlet 容器的工厂方法只接受 Map<String, String> 作为初始化参数。这个 属性 实际上是由使用 Jetty 嵌入式的第三方贡献者添加的,它确实有方法将值设置为对象的 init-params。因此,如果您需要对此的支持,您可能需要向 Jersey 提交问题。

为了扩展@peeskillet 的出色答案,在我的场景中,我不得不将我的 Jersey 应用程序与其他 servlet 一起部署在同一个 Grizzly servlet 容器中,这确实有点麻烦。

但后来我发现 https://github.com/jersey/jersey/pull/128 挽救了我的一天。查看那个拉取请求,这就是我想出的:

WebappContext webappContext = new WebappContext("myWebappContext");

webappContext.addListener(new ServletContextListener() {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        sce.getServletContext().setAttribute(ServletProperties.SERVICE_LOCATOR, MY_SERVICE_LOCATOR);
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) { }
});

ServletRegistration servlet = webappContext.addServlet("myAppplication", new ServletContainer(resourceConfig));
servlet.addMapping("/application/*");

ServletRegistration hello = webappContext.addServlet("myServlet", MyServlet.class);
hello.addMapping("/servlet/*");

HttpServer createHttpServer = GrizzlyHttpServerFactory.createHttpServer(MY_URI, false);
webappContext.deploy(createHttpServer);
createHttpServer.start();