简体   繁体   English

关于使用Jersey和Guice进行RESTful服务的实用建议

[英]Practical advice on using Jersey and Guice for RESTful service

From what I can find online, the state of the art for Guice + Jersey integration has stagnated since 2008 when it appears both teams reached an impasse. 从我在网上看到的情况来看,Guice + Jersey整合的最新技术水平自2008年以来一直停滞不前,当时两支球队都陷入了僵局。 The crux of the issue is that JAX-RS annotations perform field and method injection and this doesn't play nicely with Guice's own dependency injection. 问题的关键在于JAX-RS注释执行字段和方法注入,这与Guice自己的依赖注入不能很好地协作。

A few examples which I've found don't go far enough to elucidate: 我发现的一些例子远远不足以阐明:

  • Iqbalyusuf's post on Jersey + Guice on Google App Engine Java suffers from a lot of boilerplate (manually getting and calling the injector). Iqbalyusuf 在Google App Engine上发布关于Jersey + Guice的帖子Java遭受了大量的样板(手动获取和调用注入器)。 I want binding and injection should happen behind the scenes via Guice annotations. 我希望绑定和注入应该通过Guice注释在幕后发生。

  • Jonathan Curran's article Creating a RESTful service with Jersey, Guice, and JSR-250 gave me hope because it's much more current (2010), but went no further than showing how to start up a Jersey service inside of a Guice ServletModule. Jonathan Curran的文章使用Jersey,Guice和JSR-250创建一个RESTful服务给了我希望,因为它更新(2010),但没有比显示如何在Guice ServletModule中启动Jersey服务。 However, there are no examples of doing any real dependency injection. 但是,没有任何实例依赖注入的例子。 I suppose that was left as an exercise for the reader. 我想这是留给读者的练习。 Curran's post may in fact be the correct first step towards wiring up Guice and Jersey and so I plan on starting with that. Curran的帖子实际上可能是连接Guice和Jersey的正确的第一步,所以我打算从那开始。

  • tantalizingly James Strachan writes : 令人着迷的詹姆斯斯特拉坎写道

    JAX-RS works well with dependency injection frameworks such as Spring, Guice, GuiceyFruit or JBossMC - you can basically pick whichever one you prefer. JAX-RS适用于依赖注入框架,如Spring,Guice,GuiceyFruit或JBossMC - 你基本上可以选择你喜欢的任何一个。

    But I see no evidence that is true from a practitioner's point of view. 但是,从实践者的角度来看,我没有看到任何证据。

What I find lacking are practical examples and explanations on how to combine JAX-RS and Guice annotations. 我发现缺少的是关于如何组合JAX-RS和Guice注释的实际示例和解释。 For instance: 例如:

  • I believe I cannot use constructor injection with any resource as Jersey wants to control this 我相信我不能对任何资源使用构造函数注入,因为Jersey想控制它
  • I'm uncertain whether I can combine @Inject with @PathParam, @QueryParam, et al. 我不确定是否可以将@Inject与@PathParam,@ QueryParam等结合起来。
  • How to use injection in a MessageBodyWriter implementation 如何在MessageBodyWriter实现中使用注入

Does anyone have examples, preferably with source, of non-trivial application which combines Jersey and Guice without sacrificing one or the other in the process? 有没有人有一些非平凡的应用程序的例子,最好是源代码,它结合了Jersey和Guice,而不会在这个过程中牺牲一个或另一个? I'm keeping on this road regardless, but the bits and pieces on the Jersey and Guice lists makes me think I'm repeating the work of others who came before me. 无论如何我都会坚持这条道路,但泽西和吉斯的名单上的点点滴滴让我觉得我正在重复在我面前的其他人的工作。

Guice integration with Jersey has not stagnated. Guice与泽西的整合并没有停滞不前。 The opposite is true. 反之亦然。 Thanks to Paul and his cohorts behind Jersey, the latest 1.7 release contains a special JerseyServletModule class to work with Guice-based servlets. 感谢Paul和他在Jersey后面的同伙,最新的1.7版本包含一个特殊的JerseyServletModule类,可以与基于Guice的servlet一起使用。 Guice-based constructor injection into JAX-RS resource works! 基于Guice的构造函数注入到JAX-RS资源中的工作原理! The issue is using JAX-RS annotations such as @QueryParam in the constructor of a JAX-RS resource. 问题是在JAX-RS资源的构造函数中使用JAX-RS注释,例如@QueryParam。 You don't need it! 你不需要它! You use Guice for POJO injection all the way including singletons. 你使用Guice进行POJO注射,包括单身。 Then JAX-RS is just icing on the cake for parsing HTTP-based RESTful APIs such as URL path, query parameters, content-type and etc. You don't need an "industrial strength" example either. 然后,JAX-RS就像解析基于HTTP的RESTful API(例如URL路径,查询参数,内容类型等)一样锦上添花。您也不需要“工业强度”示例。 Both Guice and Jersey are already battle tested. Guice和Jersey都已经过战斗测试。 You just need a complete working example to see how it works. 您只需要一个完整的工作示例即可了解其工作原理。 Then you can experiment advanced features on your own. 然后,您可以自己试验高级功能。 Check out the following link for a complete example using Guice 3.0 and Jersey 1.7, which are all latest releases: 有关使用Guice 3.0和Jersey 1.7的完整示例,请查看以下链接,这些都是最新版本:
http://randomizedsort.blogspot.com/2011/05/using-guice-ified-jersey-in-embedded.html http://randomizedsort.blogspot.com/2011/05/using-guice-ified-jersey-in-embedded.html

I created a Guice/Jersey/Jetty/Jackson sample application here: 我在这里创建了一个Guice / Jersey / Jetty / Jackson示例应用程序:

http://github.com/sunnygleason/j4-minimal http://github.com/sunnygleason/j4-minimal

If you have any questions or suggestions for how to improve the example, feel free to message me via github. 如果您对如何改进示例有任何疑问或建议,请随时通过github给我发消息。 The goal is to make this a very accessible introduction to REST on the Java stack. 目标是使其成为Java堆栈上REST的非常容易获得的介绍。

Hope this helps - have a great day! 希望这有帮助 - 祝你有个美好的一天!

-Sunny -Sunny

Inspired by Sunnys sample application I've created a similar sample project that uses standard WAR files for deployment, eg in Apache Tomcat. 受Sunnys示例应用程序的启发,我创建了一个类似的示例项目,该项目使用标准WAR文件进行部署,例如在Apache Tomcat中。 You can find the project here: 你可以在这里找到这个项目:

https://github.com/danbim/template-guice-jersey-tomcat https://github.com/danbim/template-guice-jersey-tomcat

Have fun! 玩得开心! Daniel 丹尼尔

I believe I cannot use constructor injection with any resource as Jersey wants to control this 我相信我不能对任何资源使用构造函数注入,因为Jersey想控制它

You cannot use guice's constructor injection because creation of resource is managed by jersey. 你不能使用guice的构造函数注入,因为资源的创建是由jersey管理的。 In this case you can use jersey's @Inject annotation before constructor parameter you want to get injected: 在这种情况下,您可以在要注入的构造函数参数之前使用jersey的@Inject注释:

public NewsResource(@Inject NewsService service)

Although Sunny Gleason's example is great, it is a bit outdated now. 虽然Sunny Gleason的例子很棒,但现在有点过时了。

So, after struggling a lot today trying to make Guice and Jersey play nice with each other, I created the following sample project to get you started: 因此,在今天努力让Guice和Jersey相互配合之后挣扎了很多,我创建了以下示例项目来帮助您入门:

https://github.com/MaliciousMustard/gradle-guice-jersey-jetty https://github.com/MaliciousMustard/gradle-guice-jersey-jetty

This project is using the following technologies: 该项目使用以下技术:

  1. Guice for DI DI的Guice
  2. Jersey for the RESTful API Jersey for RESTful API
  3. Jackson for POJO to JSON mapping 杰克逊为POJO到JSON映射
  4. Jetty for the web-server Jetty用于Web服务器
  5. Gradle 摇篮

I guess the most important thing is that you don't have to explicitly specify every new resource class you're adding. 我想最重要的是你不必明确指定你要添加的每个新资源类。 As long as you're adding them to the package that is being scanned (look at malicious.mustard.modules.JerseyModule ), they will be found automatically! 只要您将它们添加到正在扫描的包中(查看malicious.mustard.modules.JerseyModule ),它们就会自动找到!

I was having similar problems initially trying to use Guice to do constructor injection on my Jersey annotated classes, but eventually got it working, albeit with a fairly trivial application. 我最初尝试使用Guice在我的Jersey注释类上进行构造函数注入时遇到了类似的问题,但最终还是让它工作了,尽管有一个相当简单的应用程序。

I followed the instructions here: jersey-guice javadoc 我按照这里的说明: jersey-guice javadoc

The trick in my case was that I needed to remove the standard Jersey configuration from my web.xml (like the Jersey ServletContainer) and keep only the Guice listener and Guice filter. 在我的情况下,我需要从我的web.xml中删除标准的Jersey配置(比如Jersey ServletContainer)并且只保留Guice监听器和Guice过滤器。 Once I did that Guice was being called to create my JAX-RS annotated object, and Jersey was injecting my JAX-RS annotated methods (like @GET, etc.) as expected. 一旦我这样做,Guice被调用来创建我的JAX-RS注释对象,并且Jersey按预期注入我的JAX-RS注释方法(如@GET等)。

GWizard includes a module that gives you out-of-the-box integration between Jersey2 and Guice. GWizard包含一个模块,可以让您在Jersey2和Guice之间进行开箱即用的集成。 Here's an example of a complete JAX-RS service: 以下是完整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(Run.class).start();
    }
}

Note that this is based on the Squarespace jersey2-guice adapter , which may not function properly with future point releases of Jersey. 请注意,这是基于Squarespace jersey2-guice适配器 ,它可能无法正常使用Jersey的未来版本。 GWizard also offers a RESTEasy JAX-RS module, which is preferred. GWizard还提供RESTEasy JAX-RS模块,这是首选。

Here is a blog entry about this that might help: http://blorn.com/post/107397841765/guice-and-jersey-2-the-easy-way 以下是有关此内容的博客文章可能有所帮助: http//blorn.com/post/107397841765/guice-and-jersey-2-the-easy-way

These examples were all great starts for me, but I wanted a full MVC stack using Jersey-Guice at it's core. 这些例子对我来说都是很好的开始,但我想要使用Jersey-Guice的完整MVC堆栈。 I've been working on refining that for sometime. 我一直在努力提炼它。 As of this week this MVC stack is fully deployed to Maven Central repository as an archetype. 截至本周,这个MVC堆栈作为原型完全部署到Maven Central存储库。 This means you can now create a new Jersey-Guice stack with one Maven command: 这意味着您现在可以使用一个Maven命令创建一个新的Jersey-Guice堆栈:

mvn archetype:generate \
    -DarchetypeGroupId=org.duelengine \
    -DarchetypeArtifactId=duel-mvc-archetype \
    -DarchetypeVersion=0.2.1

This automatically generates your own project with you specified package naming so you don't have to manually edit a template project. 这将使用您指定的包命名自动生成您自己的项目,因此您不必手动编辑模板项目。

See the project Readme.md for more details: https://bitbucket.org/mckamey/duel-mvc 看到项目Readme.md了解更多详情: https://bitbucket.org/mckamey/duel-mvc

Details on the dual-side views (client-side template & server-side views) I use are here: https://bitbucket.org/mckamey/duel but you could replace with whatever you use. 我使用的双面视图(客户端模板和服务器端视图)的详细信息在这里: https//bitbucket.org/mckamey/duel但您可以替换为您使用的任何内容。

I created a Guice 4.2, Jetty 9.4 and Jersey 2.7 sample application: 我创建了一个Guice 4.2,Jetty 9.4和Jersey 2.7示例应用程序:

https://github.com/bnsd55/jetty-jersey-guice-starter-kit https://github.com/bnsd55/jetty-jersey-guice-starter-kit

As Sunny said: 正如Sunny所说:

If you have any questions or suggestions for how to improve the example, feel free to message me via github. 如果您对如何改进示例有任何疑问或建议,请随时通过github给我发消息。 The goal is to make this a very accessible introduction to REST on the Java stack. 目标是使其成为Java堆栈上REST的非常容易获得的介绍。

我找到了一个有趣的Jetty + Guice + Jackson网络服务项目: https//github.com/talis/jersey-common/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM