实施Jersey 2 Spring集成

Jersey是Oracle提供的出色的Java JAX-RS规范参考实现。 去年,当我们开始为大容量网站构建RESTful后端Web服务时,我们选择使用JAX-RS API作为我们的REST框架和Spring框架来进行依赖项注入。 泽西岛是我们选择的JAX-RS实现。

项目启动时,JAX-RS API 2.0规范尚未发布,Jersey 2.0也未发布。 由于我们没有看到JAX-RS 1.1的任何根本缺陷,并且因为存在针对Jersey 1.1的稳定的Spring集成模块,所以我们决定使用经过实践检验的版本,而不是采用前沿技术。

尽管如此,我还是想知道采用更新版本会获得什么,所以我开始在业余时间看一下JAX-RS 2 API并使用Jersey 2做一些原型设计。我注意到Jersey 2缺乏与Spring框架集成的功能,适用于以前的版本。 进一步研究该问题,我发现旧的Spring集成模块无法直接移植到Jersey2。原因是Jersey 1建立在自定义内部依赖注入框架上,而Jersey 2已切换到HK2进行依赖注入。 ( HK2是在GlassFish中使用的有趣的,轻量级的依赖注入框架。)

我实现Jersey-Spring集成的最初目标非常简单:

将在应用程序上下文XML中声明的Spring bean注入到JAX-RS资源类中(使用@Autowired批注或XML配置)

因此,我认为我需要更深入地研究,并开始研究Jersey的源代码。 我很高兴地注意到,泽西岛的开发正在以开放和平易近人的方式进行。 源代码托管在GitHub上并经常更新。 经过一段时间的挖掘,Jersey Spring集成的高级设计开始形成。 在第一个可运行的原型制作之前,进行了大量的实验和多次迭代。 那时,作为一个乐观主义者,我希望我快完成了,并联系了球衣用户的邮件列表以获取有关设计和实现的反馈。 反馈:添加更多用例,提供示例代码,实现测试自动化,签署Oracle贡献者协议(从泽西软件产品的角度来看,反馈当然是非常合理的)。 因此,虽然还没有完全回到绘图板上,但是到了这一点,我意识到最后一英里要比我期望的要长得多。

最终,Jersey-Spring集成最终合并到Jersey v2.2版本的Jersey 2代码库中。 集成API基于注释,并支持以下功能:

  • 将Spring bean注入到Jersey管理的JAX-RS资源类中(使用org.springframework.beans.factory.annotation.Autowired或javax.inject.Inject)。 @Qualifier和@Named批注可用于进一步限定注入的实例。
  • 允许JAX-RS资源类实例生命周期由Spring而不是Jersey管理(org.springframework.stereotype.Component)
  • 支持不同的Spring bean注入范围:单例,请求,原型。 Bean作用域在applicationContext.xml中声明。

实施

Jersey-Spring集成的源代码可在主Jersey源存储库中找到: https : //github.com/jersey/jersey/tree/2.5.1/ext/spring3/src/main/java/org/glassfish/球衣/服务器/Spring

Jersey-Spring集成包含以下实现类:

org.glassfish.jersey.server.spring.SpringComponentProvider

该ComponentProvider实现已在Jersey SPI扩展机制中注册,它负责引导Jersey 2 Spring集成。 它使Jersey跳过了Spring组件的JAX-RS生命周期管理。 否则,Jersey会将这些类绑定到具有Jersey默认范围的HK2 ServiceLocator,而无需遵守为Spring组件声明的范围。 该类还初始化HK2弹簧桥,并向HK2 ServiceLocator注册Spring @Autowired注释处理程序。 当在servlet上下文之外运行时,将定制的org.springframework.web.context.request.RequestScope实现配置为实现Bean的请求范围。

org.glassfish.jersey.server.spring.AutowiredInjectResolver

HK2注入解析器,注入使用Spring框架@Autowired注释声明的依赖项。 HK2调用此解析器,并要求它解析使用@Autowired注释的依赖项。

org.glassfish.jersey.server.spring.SpringLifecycleListener

处理容器生命周期事件。 重新加载时刷新Spring上下文,并在关闭时将其关闭。

org.glassfish.jersey.server.spring.SpringWebApplicationInitializer

一个便利类,可帮助用户避免在web.xml中配置Spring ContextLoaderListener和RequestContextListener。 或者,用户可以在Web应用程序web.xml中配置它们。

除了实际的实现代码之外,该集成还包括示例和测试 ,这对于使开发人员入门非常有帮助。

JAX-RS规范定义了自己的依赖项注入API。 另外,Jersey支持不受JAX-RS规范要求的JSR 330样式注入。 Jersey-Spring集成增加了对Spring样式注入的支持。 JAX-RS注入和Spring集成都提供了一种将对象绑定到注册表中的机制,以便以后可以查找和注入对象。 如果使用的是完整的Java EE应用程序服务器(例如Glassfish),则还可以选择通过CDI API绑定对象。 在非Java EE环境中,可以通过嵌入容器实现(例如Weld)来使用CDI。 另一个绑定方法是使用Jersey特定的API。 测试代码包括一个JAX-RS应用程序类,该类演示了如何完成此工作。

修改球衣Spring

如果您想在Jersey-Spring上工作,则需要查看Jersey 2的代码库并进行构建。 该过程相当容易并且有据可查: https : //jersey.java.net/documentation/2.5.1/how-to-build.html

您只需要克隆存储库并构建源即可。 构建系统基于Maven。 您还可以使用其Maven插件轻松地将代码库导入所选的IDE(与IDEA 12,Eclipse 4.3和NetBeans 8.0 beta进行了尝试)。 但是,我注意到,某些集成测试在Maven 3.0中失败了,我不得不升级到3.1,但是除此之外,没有任何问题。

构建Jersey 2之后,您可以修改Spring集成模块,并仅构建更改的模块以节省时间。

测验

Jersey-Spring集成测试已使用Jersey测试框架构建 ,并且在maven-failsafe-plugin的控制下运行。 集成测试由实际的测试代码和测试执行的JAX-RS后端Webapp组成。 使用jetty-maven-plugin将后端部署到外部Jetty servlet容器中。 Jersey-Spring测试可以与其余测试分开执行。 集成测试可以在以下单独的Maven子模块中找到: https : //github.com/jersey/jersey/tree/2.5.1/tests/integration/spring3

除了演示Jersey-Spring的基本功能外,这些测试还展示了如何使用不同的Spring bean范围:单例,请求,原型。 测试还展示了使用JAX-RS应用程序类在不同范围内在容器中注册您自己的依赖项。

结论

我认为JAX-RS 2.0 API提供了一种在Java中实现RESTful接口的好方法。 Jersey JAX-RS参考实现的开发正在以公开透明的方式进行。 泽西岛还有大量活跃的用户社区。

正如小弗雷德里克·布鲁克斯(Frederick Brooks,Jr.)所说:“所有程序员都是乐观主义者”。 通常很容易低估将代码与相对较大和复杂的代码库集成所需的工作量,尤其是当您需要在多个不同框架(在此例中为Jersey,HK2和Spring框架)之间进行调解时。 此外,尽管Jersey拥有相当不错的用户文档,但我错过了有关设计和实现的高级体系结构文档。 为了确定正确的集成点,需要进行大量的探索。 幸运的是,Jersey构建系统非常易于使用,并且仅允许构建选定的零件,这使得实验和变更-构建-测试周期相对较快。

Jersey和Spring框架都提供了丰富的功能集,您可以通过多种方式一起使用它们。 当前形式的Jersey-Spring集成涵盖了两者之间的几个基本集成方案。 如果发现您的特定情况不受支持,请加入jersey-users邮件列表进行讨论。 您还可以检出代码,实施更改并通过在GitHub上提交拉取请求来贡献它们。

参考:在实践技术博客上,由我们的JCG合作伙伴 Marko Asplund 实现了Jersey 2 Spring集成 。

翻译自: https://www.javacodegeeks.com/2014/02/implementing-jersey-2-spring-integration.html

你可能感兴趣的:(实施Jersey 2 Spring集成)