【问题标题】:How to use guice-servlet with Jersey 2.0?如何在 Jersey 2.0 中使用 guice-servlet?
【发布时间】:2013-06-21 13:04:47
【问题描述】:

是否有任何示例代码演示如何在 Jersey 2.0 中使用 guice-servlet?

【问题讨论】:

  • 您想使用 guice-servlet 有什么特别的原因吗? Jersey 2.0 与开箱即用的 HK2 依赖注入完全集成,这(据我所知)与 Guice DI 非常相似。请查看stackoverflow.com/questions/16216759/… 了解更多信息。
  • @joscarsson,我不想再学习另一个 DI 框架。从功能和社区的角度来看,HK2 远不如 Guice 成熟。

标签: guice-servlet jersey-2.0


【解决方案1】:

HK2官方有一个关于正确guice实现的页面:https://javaee.github.io/hk2/guice-bridge.html

你应该像这样创建你的注入器:

  public class GuiceConfig extends ResourceConfig {

        @Inject
        public GuiceConfig(ServiceLocator serviceLocator) {
            this();
            GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
            GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
            guiceBridge.bridgeGuiceInjector(GuiceListener.createBiDirectionalGuiceBridge(serviceLocator));
        }

        public GuiceConfig() {
            packages(Injections.packages);
            addProperties(Injections.propertiesMap);
        }
    }

文档中的代码应该升级如下:

   @WebListener
    public class GuiceListener extends GuiceServletContextListener {

        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            Locale.setDefault(Locale.ENGLISH);
            super.contextInitialized(servletContextEvent);
        }

        public static volatile Injector injector = null;

        @Override
        protected Injector getInjector() {
            return injector;

        }

        @SuppressWarnings("unchecked")
        private static Module getModule() {
            return binder -> {
                Injections.singletonInterfaces.forEach((i, c) -> binder.bind(i).to(c).in(Scopes.SINGLETON));
                Injections.singletonClasses.forEach(c -> binder.bind(c).in(Scopes.SINGLETON));
            };
        }

        static synchronized Injector createBiDirectionalGuiceBridge(ServiceLocator serviceLocator) {

            return GuiceListener.injector = createBiDirectionalGuiceBridge(serviceLocator, getModule());
        }

    }

在 pom.xml 中使用 maven 依赖项

   <dependency>
        <groupId>org.glassfish.hk2</groupId>
        <artifactId>guice-bridge</artifactId>
        <version>2.3.0</version>
    </dependency>

https://github.com/phxql/jersey2-guice 不适用于 jersey 2.22 和 guice 4.0。

【讨论】:

【解决方案2】:

GWizard 包含一个模块,可让您在 Jersey2 和 Guice 之间进行开箱即用的集成。下面是一个完整的 JAX-RS 服务示例:

public class Main {
    @Path("/hello")
    public static class HelloResource {
        @GET
        public String hello() {
            return "hello, world";
        }
    }

    public static class MyModule extends AbstractModule {
        @Override
        protected void configure() {
            bind(HelloResource.class);
        }
    }

    public static void main(String[] args) throws Exception {
        Guice.createInjector(new MyModule(), new JerseyModule()).getInstance(WebServer.class).startJoin();
    }
}

请注意,这是基于 Squarespace jersey2-guice adapter,它可能无法在 Jersey 的未来版本中正常运行。 GWizard 还提供了一个 RESTEasy JAX-RS 模块,这是首选。

这里有一篇关于此的博客文章可能会有所帮助:http://blorn.com/post/107397841765/guice-and-jersey-2-the-easy-way

【讨论】:

    【解决方案3】:

    我已经完成了这个示例:

    https://github.com/jbescos/tododev

    您必须在 ResourceConfig 中注册类 https://github.com/jbescos/tododev/blob/master/jersey2-guice/src/main/java/es/tododev/rest/ApplyGuiceContextFilter.java,并且在 AbstractModule 中绑定 guice 注入器。

    @Provider
    @PreMatching
    public class ApplyGuiceContextFilter implements ContainerRequestFilter, ContainerResponseFilter {
    
        @Inject
        public ApplyGuiceContextFilter(ServiceLocator serviceLocator, Injector injector) {
            GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
    
            GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
            guiceBridge.bridgeGuiceInjector(injector);
        }
    
        @Override
        public void filter(final ContainerRequestContext requestContext) throws IOException {
    
        }
    
        @Override
        public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws IOException {}
    }  
    

    这是ResouceConfig

    public class RestConfig extends ResourceConfig {
    
        @Inject
        public RestConfig() {
            this(Guice.createInjector(new Module(){
                @Override
                public void configure(Binder arg0) {
                    // TODO Auto-generated method stub
                }
            }));
        }
    
        // Test
        public RestConfig(Injector injector) {
            packages(ResourceSample.class.getPackage().getName());
            register(ApplyGuiceContextFilter.class);
            register(new LoggingFilter(Logger.getLogger(LoggingFilter.class.getName()), true));
    
            property(ServerProperties.TRACING, "ALL");
            register(new RestBinder(injector));
        }
    
        private static class RestBinder extends AbstractBinder{
    
            private final Injector injector;
    
            private RestBinder(Injector injector){
                this.injector = injector;
            }
    
            @Override
            protected void configure() {
                bind(injector).to(Injector.class);
            }
    
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      https://github.com/Squarespace/jersey2-guice 似乎是 Jersey 2 的第一个真正的 Guice 集成,但它需要 2.11+ 版本。

      注意:我没有对此进行测试,但这个想法是合理的。

      【讨论】:

      【解决方案5】:

      这是将 Jersey 2 和 Guice 连接在一起的最低工作 PoC:

      https://github.com/phxql/jersey2-guice

      【讨论】:

      • -1,这不支持将 guice 类型注入构造函数。
      • 在 MyResource 中注入了 Guice 的 TimeService,参见 github.com/phxql/jersey2-guice/blob/master/src/main/java/de/…
      • 这没什么区别。 HK2 桥不支持构造函数注入。
      • 我不明白,如果您将战争部署到应用服务器,它就可以工作。
      【解决方案6】:

      这是一个使用 Embedded Jetty 的示例(它应该也适用于 Jetty 服务器)

      jetty-jersey-HK2-Guice-boilerplate

      如果您计划在您的应用程序中使用 Guice,则所有注入 Jersey 的 Guice 组件都需要在 Guice 配置中声明为绑定。

      如果你不想在 Guice 配置中声明每个绑定,这里有一个适配器:

      guice-bridge-jit-injector

      【讨论】:

        【解决方案7】:

        对于那些感兴趣的人,https://github.com/mycom-int/jersey-guice-aop 提供了一个 guice/jersey 集成示例。

        【讨论】:

        • 不清楚你在这里做什么(特别是因为你谈论单向注入但没有解释你的意思是哪个方向)。您需要一个双向桥接器,因为 Jersey 总是会要求 HK2 注入(您希望 HK2 在其中委托给 Guice),而另一方面,当您要求 Guice 注入恰好包含 Jersey 类型的 Object 时(例如UriInfo) 你需要 Guice 委托给 HK2 进行注入。简而言之:单向桥是不够的。
        • 也许要澄清一下:单向桥足以将 Guice 资源注入 Jersey。如果你想使用 AOP 并混合 Guice 和 HK2,那么你肯定需要双向桥。
        • 如果不混合 Guice 和 HK2,您将很难过。我将举一个具体的例子:如果你使用 Guice 注入了 Jersey 资源,但它引用了UriInfo,那么 Guice 将需要委托给 HK2 来获取实例(但不能)。
        【解决方案8】:

        是的,我已经改编了一个示例,可以在这里找到 - https://github.com/piersy/jersey2-guice-example-with-test

        我现在已经更新了示例代码,它使用 jetty 进行了测试,使用 tomcat 进行了测试。

        【讨论】:

        • 仅适用于 Glassfish。需要一个适用于 Tomcat、Jetty 等的更通用的示例。
        • 您好 mjaggard,我不确定我是否理解您的意思,在发布的示例中,我使用的是 jetty 而不是 glassfish?
        • 对不起,我想我对 HK2 的使用感到困惑。为什么要使用它?
        • 目前还没有针对 Jersey2 的直接 Guice 集成,但是可以使用 HK2 作为桥梁来实现,请参阅 - hk2.java.net/guice-bridge/index.html
        • 我知道这有点过时了,但是这个桥的想法是有一个不同的 ResourceConfig 来使用不同的 Guice 模块吗? (比如绑定到模拟实现以进行测试。)
        猜你喜欢
        • 2013-08-07
        • 2013-09-29
        • 1970-01-01
        • 2012-08-12
        • 1970-01-01
        • 2018-09-20
        • 1970-01-01
        • 2011-11-04
        相关资源
        最近更新 更多