拥抱模块化Java平台:Java 10上的Apache CXF

Java 9版本终于将Project Jigsaw交付给大众已经过去了一年多的时间。 这是一段漫长的旅程,但是在那里,所以发生了什么变化? 这是一个很好的问题,答案并不明显和直接。

总的来说, 拼图项目是一种颠覆性的变化,其原因很多。 尽管我们几乎所有现有应用程序都将在Java 10上运行(很快将由JDK 11取代),几乎没有变化,但Jigsaw项目给Java开发人员带来了深远的影响:拥抱Java的模块化应用程序平台方式。

由于存在无数出色的框架和库,因此将它们转换为Java模块肯定会花费很多时间,(很多人永远不会这样做)。 这条路是棘手的,但是即使在今天,某些事情也已经成为可能。 在这篇简短的文章中,我们将学习如何使用出色的Apache CXF项目,使用最新的JDK 10以真正的模块化方式构建JAX-RS 2.1 Web API 。

3.2.5版本开始,所有Apache CXF工件的清单都带有Automatic-Module-Name伪指令。 它不会使它们成为完整的模块 ,但这是朝着正确方向迈出的第一步。 因此,让我们开始吧……

如果您使用Apache Maven作为选择的构建工具,在这里没有做太多更改,则依赖项的声明方式与以前相同。

<dependencies><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxrs</artifactId><version>3.2.5</version></dependency><dependency><groupId>com.fasterxml.jackson.jaxrs</groupId><artifactId>jackson-jaxrs-json-provider</artifactId><version>2.9.6</version></dependency><dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-server</artifactId><version>9.4.11.v20180605</version></dependency><dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-webapp</artifactId><version>9.4.11.v20180605</version></dependency>
</dependencies>

uber-jar或fat-jar打包实际上不适用于模块化Java应用程序,因此我们必须自己收集模块,例如,在target / modules文件夹中。

<plugin><artifactId>maven-jar-plugin</artifactId><version>3.1.0</version><configuration><outputDirectory>${project.build.directory}/modules</outputDirectory></configuration>
</plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><version>3.1.1</version><executions><execution><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>${project.build.directory}/modules</outputDirectory><includeScope>runtime</includeScope></configuration></execution></executions>
</plugin>

很好,下一步是创建module-info.java并在其中列出我们模块的名称(在本例中为com.example.cxf ),并列出其中所有必需的模块以使其正常运行。

module com.example.cxf {exports com.example.rest;requires org.apache.cxf.frontend.jaxrs;requires org.apache.cxf.transport.http;requires com.fasterxml.jackson.jaxrs.json;requires transitive java.ws.rs;requires javax.servlet.api;requires jetty.server;requires jetty.servlet;requires jetty.util;requires java.xml.bind;
}

您可能会马上发现, org.apache.cxf.frontend.jaxrsorg.apache.cxf.transport.http来自Apache CXF发行版( 完整列表可在文档中找到 ),而java.ws.rs是JAX。 -RS 2.1 API模块。 之后,我们可以像以前一样继续实现我们的JAX-RS资源。

@Path("/api/people")
public class PeopleRestService {@GET@Produces(MediaType.APPLICATION_JSON)public Collection<Person> getAll() {return List.of(new Person("John", "Smith", "john.smith@somewhere.com"));}
}

这看起来很简单,例如,添加一些辣酱,例如服务器发送的事件 ( SSE )和RxJava呢? 从依赖关系开始,让我们看看它有多容易。

<dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-rs-sse</artifactId><version>3.2.5</version>
</dependency><dependency><groupId>io.reactivex.rxjava2</groupId><artifactId>rxjava</artifactId><version>2.1.14</version>
</dependency>

同样,我们不要忘记通过将requires指令添加到这些新模块来更新我们的module-info.java

module com.example.cxf {...requires org.apache.cxf.rs.sse;requires io.reactivex.rxjava2;requires transitive org.reactivestreams;...}

为了简单起见,我们的SSE端点只会广播通过API添加的每个新用户。 这是实现的代码段。

private SseBroadcaster broadcaster;
private Builder builder;
private PublishSubject<Person> publisher;public PeopleRestService() {publisher = PublishSubject.create();
}@Context 
public void setSse(Sse sse) {this.broadcaster = sse.newBroadcaster();this.builder = sse.newEventBuilder();publisher.subscribeOn(Schedulers.single()).map(person -> createEvent(builder, person)).subscribe(broadcaster::broadcast);
}@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response add(@Context UriInfo uriInfo, Person payload) {publisher.onNext(payload);return Response.created(uriInfo.getRequestUriBuilder().path(payload.getEmail()).build()).entity(payload).build();
}@GET
@Path("/sse")
@Produces(MediaType.SERVER_SENT_EVENTS)
public void people(@Context SseEventSink sink) {broadcaster.register(sink);
}

现在,当我们构建它时:

mvn clean package

并使用模块路径运行它:

java --add-modules java.xml.bind \--module-path target/modules \--module com.example.cxf/com.example.Starter

我们应该能够对我们的JAX-RS API进行测试。 使预期确保一切工作的最简单方法是在浏览谷歌Chrome浏览器的SSE端点的http://本地主机:8686 / API /人/ SSE ,并通过添加一些随机的人POST请求,使用老伙计卷曲从命令行:

curl -X POST http://localhost:8686/api/people \-d '{"email": "john@smith.com", "firstName": "John", "lastName": "Smith"}' \-H "Content-Type: application/json"
curl -X POST http://localhost:8686/api/people \-d '{"email": "tom@tommyknocker.com", "firstName": "Tom", "lastName": "Tommyknocker"}' \-H "Content-Type: application/json"

在Google Chrome浏览器中,我们应该能够看到由服务器推送的原始SSE事件(它们看起来不漂亮,但足以说明流程)。

Apache CXF

那么,应用程序打包呢? Docker和容器当然是一个可行的选择,但是在Java 9及更高版本中,我们还有另一个参与者: jlink 。 它将一组模块及其依赖项组装并优化为一个自定义的,足够的运行时映像。 让我们尝试一下。

jlink --add-modules java.xml.bind,java.management \--module-path target/modules \--verbose \--strip-debug \--compress 2 \--no-header-files \--no-man-pages \--output target/cxf-java-10-app

在这里,我们正在碰壁。 不幸的是,由于我们应用程序的大多数依赖项都是自动模块 ,因此对于jlink来说是个问题,并且从运行时映像运行时,我们仍然必须显式包括模块路径:

target/cxf-java-10-app/bin/java  \--add-modules java.xml.bind \--module-path target/modules \--module com.example.cxf/com.example.Starter

最终,事实并非如此可怕。 我们肯定处于JPMS采纳的初期,这仅仅是开始。 当我们使用的每个库,每个框架都在其工件(JAR)中添加module-info.java ,使它们成为真正的模块,尽管有许多怪癖 ,然后我们才能宣告胜利。 但是,小小的胜利已经在发生,请成为您的胜利!

该项目的完整资源可在Github上找到 。

翻译自: https://www.javacodegeeks.com/2018/08/modular-java-platform-apache-cxf.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346038.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab sym转str,sym struct 转换

描述&#xff1a;用 sym() 生成了 矩阵&#xff1b; 再用 solve() 结果返回 结构体&#xff0c;还带sym 型。。。尝试&#xff1a;用 struct 转换 ; eval() 什么的 都无解&#xff0c;&#xff0c; (结构体还带sym。。。。昏了)求&#xff1a;怎…

php $r,PHP

本文实例为大家分享了php微信跳一跳的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下 ?php require config.php; function similar($rgb1, $rgb2) { $r1 ($rgb1 16) $g1 ($rgb1 8) $b1 $rgb1 $r2 ($rgb2 16) $g2 ($rgb2 8) $b2 $rgb2 return abs($r1 - $r2) 1…

java 字符串对齐_最佳字符串对齐的Java实现

java 字符串对齐有一阵子&#xff0c;我使用了Levenshtein distance的Apache Commons lang StringUtils实现。 它实现了一些众所周知的技巧&#xff0c;通过仅挂接到两个数组而不是为备忘录表分配巨大的nxm表来使用较少的内存。 它还仅检查宽度为2 * k 1的“条带”&#xff0c;…

zabbix可以监控什么php,zabbix监控php

通过启用php-fpm的status页面&#xff0c;使用zabbix来获取各数据参数以达到监控php-fpm性能状态php-fpm配置配置文件php-fpm.confpm.status_path /fpmstatusping.path /fpmpingping.response pongnginx配置在配置的server内添加locationlocation ~ ^/(fpmstatus|fpmping) {…

建立无服务器的“ Hello World”功能

无服务器 &#xff0c;功能即服务&#xff08;FaaS&#xff09;或仅具有云功能&#xff0c;就可以编写将在云中运行的代码。 您可以使用多种不同的语言&#xff08;例如JavaScript&#xff08;Node.js&#xff09;&#xff0c;Swift&#xff0c;Python&#xff0c;Java&#xf…

oracle 10g 分区管理,Oracle 10g分区表的自动维护

Oracle 10g分区表不支持自动化管理&#xff0c;一般都要手动创建分区&#xff0c;手动删除。今天给大家带来了一个自动化管理表空间的脚本。本脚本主要由3个部分组成&#xff1a;sys_ConfigTable.sql、sys_pro_AddAndDropPartition.sql、sys_pro_MergeTable.sql1、sys_ConfigTa…

Oracle12如何重装,Oracle怎么重新安装?

实现方法&#xff1a;1、 开始&#xff0d;&#xff1e;设置&#xff0d;&#xff1e;控制面板&#xff0d;&#xff1e;管理工具&#xff0d;&#xff1e;服务 停止所有Oracle服务。2、 开始&#xff0d;&#xff1e;程序&#xff0d;&#xff1e;Oracle - OraHome81&#xff…

java实现metro风格_Metro风格的Java组合框(JMetro)–重新介绍

java实现metro风格我上一篇关于JMetro的文章–我的都市风格的Java皮肤&#xff08;或外观&#xff09;是关于日历选择器控件的 。 我本打算使用Tom Eugelink不错的日历选择器&#xff0c;但当时我了解到它是由Oracle创建并随Java 8一起提供的&#xff0c;因此出于时间的考虑&am…

Istio的网络API解释了

Istio 1.0版附带一个网络API&#xff0c;该API包含许多功能并涵盖了各种情况。 联网API在最近几个月中得到了发展&#xff0c;并且可能无法立即说明。 该API的概念和构建块是什么&#xff0c;以及如何使用各个Istio资源类型来通过我们的服务网格路由流量&#xff1f; 尽管文档…

toad查看oracle的plsql包,Oracle logminer 分析redo log(TOAD与PLSQL)

Oracle logminer 分析redo logOracle 11g r2 RAC centos 6.5设置时间格式select to_char(sysdate,yyyy-mm-dd hh24:mi:ss) date_format from dual ;查看数据库是否开启补全日志功能selectSUPPLEMENTAL_LOG_DATA_MIN,SUPPLEMENTAL_LOG_DATA_PK,SUPPLEMENTAL_LOG_DATA_UI,SUPPLEM…

php里面的mark,PHP CommonMarkCQL 用法 手册 | 示例代码

简介CommonMark Query Language is a DSL for describing how to travel through a CommonMark Node tree implemented as a parser and compiler for a small set of instructions, and a virtual machine for executing those instructions.Paths:In its most simplistic for…

spring 面向接口编程_Spring面向方面的编程

spring 面向接口编程介绍 在理想的面向对象系统中&#xff0c;我们希望将每个对象设计为执行一项特定任务。 但是&#xff0c;除了执行其主要任务之外&#xff0c;对象还执行被动任务&#xff0c;例如日志记录&#xff0c;事务&#xff0c;安全性&#xff0c;缓存等。这些被动活…

Nutshell中的Java 8语言功能-第2部分

编者注&#xff1a;您也可以在此处检查Part-1。 嗨&#xff0c;朋友们&#xff0c;这是简明系列的Java 8语言功能的第2部分。 在这里&#xff0c;我们将讨论Java 8的以下功能&#xff1a; 接口中的静态方法 流 1.接口中的静态方法 什么是静态方法&#xff1f; 静态方法是属…

概率

概率 概率质量函数&#xff08;probability mass function, PMF&#xff09;针对的是离散变量 常见的离散随机变量分布的PMF函数&#xff1a;伯努利分布&#xff0c;二项分布&#xff0c;泊松分布。 概率密度函数&#xff08;probability density function, PDF&#xff09;针…

oracle impdp导入时卡住,Oracle:impdp导入等待statement suspended, wait error to be cleared

用数据泵impdp往开发数据库导数据&#xff0c;但导入到INDEX时感觉卡住不动了Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX----查看状态&#xff0c;Completed Objects: 33一直没有变化。Import> statusJob: SYS_IMPORT_FULL_01Operation: IMPORTMode: FULLStat…

梯度下降法、最速下降法

梯度下降法 最优化问题是求解函数极值的问题&#xff0c;包括极大值和极小值。相信所有的读者对这个问题都不陌生&#xff0c;在初中时我们就学会了求解二次函数的极值&#xff08;抛物线的顶点&#xff09;&#xff0c;高中时学习了幂函数&#xff0c;指数函数&#xff0c;对…

php ajax 表格编辑,php ajax表格实时编辑 PHP Ajax实现表格实时编辑

想了解PHP Ajax实现表格实时编辑的相关内容吗&#xff0c;佛祖的腿毛在本文为您仔细讲解php ajax表格实时编辑的相关知识和一些Code实例&#xff0c;欢迎阅读和指正&#xff0c;我们先划重点&#xff1a;php,ajax表格实时编辑,ajax实现表格编辑&#xff0c;下面大家一起来学习吧…

jpa和hibernate_使用JPA和Hibernate有效删除数据

jpa和hibernate您可能会遇到必须对关系数据库中存储的大量数据集执行批量删除的情况。 如果您将JPA与Hibernate一起用作基础OR映射器&#xff0c;则可以尝试通过以下方式调用EntityManager的remove&#xff08;&#xff09;方法&#xff1a; public void removeById(long id) …

超越函数

代数数 在数论中&#xff0c;超越数是指任何一个不是代数数的数字&#xff08;通常它是复数&#xff09;。它满足以下条件——只要它不是任何一个整系数代数方程的根&#xff0c;它即是超越数。最著名的超越数是e以及π。 超越数 超越数的例子 所有超越数构成的集是一个不可数…

无服务器-仅仅是构建现代应用程序的一种方法?

如果搜索“无服务器”&#xff0c;则会发现无服务器是构建现代应用程序的一种新的流行方式。 无服务器真的是新的吗&#xff1f; 无服务器是指您无需担心服务器的概念-无需置备&#xff0c;部署和维护服务器。 显然有服务器&#xff0c;但是您无需考虑或担心它们&#xff0c;运…