java与java ee_RxJava + Java8 + Java EE 7 + Arquillian =幸福

java与java ee

消防React管理_DigitalStorm_226x150

服务是一种体系结构样式,其中每个服务都实现为一个独立的系统。 他们可以使用自己的持久性系统(尽管不是强制性的),部署,语言等。

由于系统由一个以上的服务组成,因此每个服务将与其他服务通信,通常使用轻量级协议(如HTTP)并遵循Restful Web方法。 您可以在这里阅读有关微服务的更多信息: http : //martinfowler.com/articles/microservices.html

让我们看一个非常简单的例子。 假设我们有一家售票店,用户可以在其中浏览目录,当他们找到想要查看更多信息的书时,单击isbn,然后会打开一个新屏幕,其中包含该书的详细信息和对此的评论由读者撰写。

该系统可能由两个服务组成:

  • 一种获取书籍详细信息的服务。 可以从任何传统系统(如RDBMS)中检索它们。
  • 一种将所有评论写在书中的服务,在这种情况下,信息可以存储在文档库中。

这里的问题是,对于用户的每个请求,我们需要打开两个连接,每个服务一个。 当然,我们需要一种并行执行这些工作的方法来提高性能。 这是一个问题,我们如何处理异步请求? 第一个想法是使用Future类。 对于两个服务可能很好,但是如果您需要四个或五个服务,代码将变得越来越复杂,例如,您可能需要从一个服务获取数据并在另一服务中使用它,或者将一个服务的结果修改为输入另一个。 因此,存在线程和同步管理的成本。

有一种干净整洁的方式来解决这个问题的方法真是太棒了。 这正是RxJava所做的。 RxJava是Reactive Extensions的Java VM实现:该库用于通过使用可观察的序列来组成异步和基于事件的程序。

使用RxJava而不是从结构中提取数据,而是将数据推送到它,该数据与订阅者侦听的事件做出React并一致地起作用。 您可以在https://github.com/Netflix/RxJava中找到更多信息。

因此,在这种情况下,我们要实现的是此处描述的示例,该示例使用RxJavaJava EE 7Java 8Arquillian进行测试。

这篇文章假定您知道如何使用Java EE规范编写Rest服务。

因此,让我们从两个服务开始:

@Singleton
@Path("bookinfo")
public class BookInfoService {@GET@Path("{isbn}")@Produces(MediaType.APPLICATION_JSON)@Consumes(MediaType.APPLICATION_JSON)public JsonObject findBookByISBN(@PathParam("isbn") String isbn) {return Json.createObjectBuilder().add("author", "George R.R. Martin").add("isbn", "1111").add("title", "A Game Of Thrones").build();}}
@Singleton
@Path("comments")
public class CommentsService {@GET@Path("{isbn}")@Produces(MediaType.APPLICATION_JSON)public JsonArray bookComments(@PathParam("isbn") String isbn) {return Json.createArrayBuilder().add("Good Book").add("Awesome").build();}}
@ApplicationPath("rest")
public class ApplicationResource extends Application {
}

最后是创建第三个外观服务的时候了,该服务从客户端接收通信,并行向两个服务发送请求,最后压缩两个响应。 zip是将通过指定函数发出的一组项目组合在一起并将其发送回客户端的过程(不要与压缩混淆!)。

@Singleton
@Path("book")
public class BookService {private static final String BOOKSERVICE = "http://localhost:8080/bookservice";private static final String COMMENTSERVICE = "http://localhost:8080/bookcomments";@Resource(name = "DefaultManagedExecutorService")ManagedExecutorService executor;Client bookServiceClient;WebTarget bookServiceTarget;Client commentServiceClient;WebTarget commentServiceTarget;@PostConstructvoid initializeRestClients() {bookServiceClient = ClientBuilder.newClient();bookServiceTarget = bookServiceClient.target(BOOKSERVICE + "/rest/bookinfo");commentServiceClient = ClientBuilder.newClient();commentServiceTarget = commentServiceClient.target(COMMENTSERVICE + "/rest/comments");}@GET@Path("{isbn}")@Produces(MediaType.APPLICATION_JSON)public void bookAndComment(@Suspended final AsyncResponse asyncResponse, @PathParam("isbn") String isbn) {//RxJava code shown below}
}

基本上,我们创建一个新服务。 在这种情况下,我们将要连接的两个服务的URL都是硬编码的。 这是出于学术目的而完成的,但是在类似于生产的代码中,您将从生产者类或属性文件或用于此目的的任何系统中注入它。 然后,我们创建javax.ws.rs.client.WebTarget来使用Restful Web Service

之后,我们需要使用RxJava API实现bookAndComment方法。

RxJava中使用的主要类是rx.Observabl e。 正如他的名字所暗示的那样,此类是可观察的,并且是触发事件以推动对象的原因。 默认情况下,事件是同步的,开发人员有责任使它们异步。

因此,我们需要为每个服务提供一个异步可观察实例:

public Observable<JsonObject> getBookInfo(final String isbn) {return Observable.create((Observable.OnSubscribe<JsonObject>) subscriber -> {Runnable r = () -> {subscriber.onNext(bookServiceTarget.path(isbn).request().get(JsonObject.class));subscriber.onCompleted();};executor.execute(r);});
}

基本上,我们创建一个Observable ,当订户订阅它时将执行指定的功能。 该函数是使用lambda表达式创建的,以避免创建嵌套的内部类。 在这种情况下,由于调用bookinfo服务,我们将返回JsonObject 。 结果将传递到onNext方法,以便订阅者可以接收结果。 因为我们要异步执行此逻辑,所以代码被包装在Runnable块中。

完成所有逻辑后,还需要调用onCompleted方法。

注意,因为除了创建Runnable之外 ,我们还希望使可观察的异步发生,所以我们使用Executor在单独的线程中运行逻辑。 Java EE 7中的一项重大新增功能是在容器内部创建线程的一种托管方式。 在这种情况下,我们使用容器提供的ManagedExecutorService在当前任务的不同线程中异步跨越任务。

public Observable<JsonArray> getComments(final String isbn) {return Observable.create((Observable.OnSubscribe<JsonArray>) subscriber -> {Runnable r = () -> {subscriber.onNext(commentServiceTarget.path(isbn).request().get(JsonArray.class));subscriber.onCompleted();};executor.execute(r);});
}

与之前的内容类似,但没有获取书籍信息,而是获得了一系列评论。

然后,我们需要创建一个可观察者,负责在两个响应均可用时压缩两个响应。 这是通过在Observable类上使用zip方法完成的,该方法接收两个Observable并应用一个函数来组合两个结果。 在这种情况下,一个lambda表达式会创建一个新的json对象,附加两个响应。

@GET
@Path("{isbn}")
@Produces(MediaType.APPLICATION_JSON)
public void bookAndComment(@Suspended final AsyncResponse asyncResponse, @PathParam("isbn") String isbn) {//Calling previous defined functionsObservable<JsonObject> bookInfo = getBookInfo(isbn);Observable<JsonArray> comments = getComments(isbn);Observable.zip(bookInfo, comments, (JsonObject book, JsonArray bookcomments) ->Json.createObjectBuilder().add("book", book).add("comments", bookcomments).build()).subscribe(new Subscriber<JsonObject>() {@Overridepublic void onCompleted() {}@Overridepublic void onError(Throwable e) {asyncResponse.resume(e);}@Overridepublic void onNext(JsonObject jsonObject) {asyncResponse.resume(jsonObject);}});
}

让我们看一下以前的服务。 我们正在使用@Suspended批注来使用Java EE中的新增功能之一,即Jax-Rs 2.0异步REST端点。 基本上,我们正在做的是释放服务器资源,并使用resume方法在响应可用时生成响应。

最后是测试。 我们将Wildfly 8.1用作Java EE 7服务器和Arquillian 。 因为每个服务可以在不同的服务器上进行部署,我们将在不同的战争 ,而是同一个服务器内部署各项服务。

因此,在这种情况下,我们将部署三个战争文件,这在Arquillian中非常容易做到。

@RunWith(Arquillian.class)
public class BookTest {@Deployment(testable = false, name = "bookservice")public static WebArchive createDeploymentBookInfoService() {return ShrinkWrap.create(WebArchive.class, "bookservice.war").addClasses(BookInfoService.class, ApplicationResource.class);}@Deployment(testable = false, name = "bookcomments")public static WebArchive createDeploymentCommentsService() {return ShrinkWrap.create(WebArchive.class, "bookcomments.war").addClasses(CommentsService.class, ApplicationResource.class);}@Deployment(testable = false, name = "book")public static WebArchive createDeploymentBookService() {WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "book.war").addClasses(BookService.class, ApplicationResource.class).addAsLibraries(Maven.resolver().loadPomFromFile("pom.xml").resolve("com.netflix.rxjava:rxjava-core").withTransitivity().as(JavaArchive.class));return webArchive;}@ArquillianResourceURL base;@Test@OperateOnDeployment("book")public void should_return_book() throws MalformedURLException {Client client = ClientBuilder.newClient();JsonObject book = client.target(URI.create(new URL(base, "rest/").toExternalForm())).path("book/1111").request().get(JsonObject.class);//assertions}
}

在这种情况下,客户将要求一本书提供所有信息。 在服务器部分中, zip方法将等待直到并行检索书和注释,然后将两个响应组合到一个对象中并发送回客户端。

这是RxJava的一个非常简单的示例。 实际上,在这种情况下,我们仅看到了如何使用zip方法,但是RxJava提供了许多其他有用的方法,例如take()map()merge() ,…( https:// github .com / Netflix / RxJava / wiki / Alphabetical-Observable-Operators列表 )

此外,在此示例中,我们仅看到了连接两个服务并并行检索信息的示例,您可能想知道为什么不使用Future类。 在此示例中使用FutureCallbacks完全可以,但是在现实生活中,您的逻辑将不会像压缩两个服务那样容易。 也许您将拥有更多的服务,也许您需要从一项服务中获取信息,然后为每个结果打开一个新的连接。 如您所见,您可能从两个Future实例开始,但以一堆Future.get()方法,超时等结束,因此,在这些情况下, RxJava确实简化了应用程序的开发。

此外,我们还看到了如何使用Java EE 7的一些新增功能,例如如何使用Jax-Rs开发异步Restful服务。

在这篇文章中,我们学习了如何处理服务之间的互连以及如何使它们可伸缩并减少资源消耗。 但是,我们没有谈论这些服务之一发生故障时发生的情况。 呼叫者怎么了? 我们有办法进行管理吗? 当其中一项服务不可用时,是否有一种方法可以不浪费资源? 我们将在下一篇关于容错的文章中对此进行介绍。

我们不断学习,

亚历克斯


邦迪亚,邦迪亚! Bon dia aldematí! Fem for a la mandra I saltem corrents del llit。 (Bon Dia!–DàmarisGelabert)

翻译自: https://www.javacodegeeks.com/2014/07/rxjava-java8-java-ee-7-arquillian-bliss.html

java与java ee

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

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

相关文章

【PPT】折线线条怎么画?

大家晚上好~ 今天跟大家分享3种绘制折线线条的方法。在模仿PPT的时候发现没有折线形状&#xff0c;这可怎么好呢&#xff1f; 今天带来了3种快速制作折线线条的方式&#xff0c;让我们一起围观学习吧~ 方法1 形状布尔运算出折线线条 在PPT默认的形状里没有折线&#xff0c;那…

创建通用数组的问题

在这篇文章中&#xff0c;我们将介绍一篇全面的文章&#xff0c;其中介绍了创建通用数组的问题。 Java编程语言于2004年9月在Java 5.0“ Tiger”发行版中添加了泛型。 泛型或类型参数化系统在提供类型安全性的同时扩展了Java现有的类型系统。 1.简介 Java具有Collections Fram…

Citavi阅读PDF文件中目录位置

一般阅读pdf文件&#xff0c;如果文件内内嵌目录数据&#xff0c;可以根据目录&#xff0c;跳转到PDF文件的对应章节。 citavi也不例外 citavi调出目录章节位置如下图所示&#xff1a; 1. 点击左下方的搜索框 2. 点击目录标志 即可调出目录窗口

Ubuntu下命令行解析

Linux命令通常由以下三部分组成&#xff1a;Command [-option] [argument] 其中&#xff0c;命令为程序的名称。选项和参数可以省略 选项中one dash&#xff08;-&#xff09;与two dashes&#xff08;--&#xff09;区别 使用命令时常看到有时候为选项为-&#xff0c;有时候…

使用JMeter进行性能测试

在开发复杂的高可用性软件项目时&#xff0c;性能至关重要。 在当今这样的现代时代尤其如此&#xff0c;除了闪电般的快速访问实时数据之外&#xff0c;其他任何事情都受到惩罚。 当谈论有时需要的大量数据时&#xff0c;这并不总是一件容易的事。 在本文中&#xff0c;我们将…

Unix系统用户下载内容存放位置

1.Unix文件目录含义 首先注意usr 指 Unix System Resource&#xff0c;而不是User 然后通常&#xff1a; /usr/bin下面的都是系统预装的可执行程序&#xff0c;会随着系统升级而改变。 /usr/local/bin目录是给用户放置自己的可执行程序的地方&#xff0c;推荐放在这里&…

Linux depmod功能说明

Linux depmod 命令用于分析可载入模块的相依性。 depmod(depend module)可检测模块的相依性&#xff0c;供modprobe在安装模块时使用。 Linux modprobe命令用于自动处理可载入模块。 modprobe可载入指定的个别模块&#xff0c;或是载入一组相依的模块。modprobe会根据depmod…

jboss eap_带有自定义模块的JBoss EAP上的骆驼

jboss eapApache Camel —最好的开源集成库 Apache Camel是一个很棒的开放源代码集成库&#xff0c;可以用作ESB的主干或在独立的应用程序中进行系统的路由&#xff0c;转换或中介&#xff08;请参阅&#xff1a;集成多个系统&#xff09;。 Camel非常通用&#xff0c;不会迫使…

ubuntu下安装openMPI

首先访问openmpi官网:Openmpi 然后选择Download&#xff0c;进入资源下载页面。选择最新版本的openmpi 如何获得下载链接呢&#xff1f;将鼠标放在openmpi-4.0.5.tar.gz 上右击&#xff0c;然后选择复制链接地址。打开远程命令窗口&#xff0c;进入root或者用户模式。 (1)、下…

前6个最常用的Redis库

Redis目前 是世界上最受欢迎的键值商店&#xff0c; 它通过提供高速和低延迟以及针对应用程序开发人员的灵活功能集&#xff0c;赢得了广泛的采用率 。 Redis是一个内存数据结构存储&#xff0c;用作根据BSD许可分发的数据库&#xff0c;缓存和消息代理 。 许多领先的技术品牌…

拓扑排序算法总结

知识概览 求图的拓扑序是图的宽搜的一个很经典的应用&#xff0c;拓扑序列是针对有向图来说的。 拓扑序列的定义是&#xff1a; 如果说一个点的序列满足对于图中的每条有向边(x, y)&#xff0c;x都出现在y的前面&#xff0c;那就称这个序列是这个图的拓扑序列。 备注&#xff…

Ns3使用MPI加速仿真速度

Ns3中在大规模拓扑仿真中&#xff0c;为加速仿真速度&#xff0c;可以利用MPI工具&#xff0c;实现多进程联合仿真。 linux系统下安装openmpi. 参考链接# ubuntu下安装openMPI成功运行ns-3中的文件 命令1:sudo gedit /etc/profile打开文件&#xff0c;加入ns-3的路径: 最后此文…

代码中 #ifdef注释方法的使用

1 代码中 #ifdef注释方法的使用 #ifdef的使用 #ifdef _XXXX ...程序段1... #else ...程序段2... #endif如果标识符_XXXX已经被#define定义&#xff0c;则编译程序段&#xff11;&#xff0c;否则编译程序段&#xff12;&#xff0e;#else非必须&#xff0c;可不存在程序段&am…

input发送a.jax_JAX-RS 2.0的新功能– @BeanParam批注

input发送a.jax至少可以说JAX-RS很棒&#xff0c;也是我的最爱之一&#xff01; 为什么&#xff1f; 功能丰富 直观&#xff08;因此学习曲线不那么陡峭&#xff09; 易于使用和开发 具有出色的RI – Jersey &#xff0c; RestEasy等 有足够的JAX-RS粉丝可以添加此内容&am…

常用的\与/的区别

1 常用的\与/的区别 1.1 正斜杠/ 正斜杠"/"一般作为除法符号或者间隔符号使用&#xff0c;主要用于间隔使用。 在unix系统中&#xff0c;/ 表示目录。由于web遵循unix命名&#xff0c;所以在网址&#xff08;URL&#xff09;中&#xff0c;/ 表示目录 1.2 反斜杠 …

Netty Java快速指南

使用Okta的身份管理平台轻松部署您的应用程序 使用Okta的API在几分钟之内即可对任何应用程序中的用户进行身份验证&#xff0c;管理和保护。 今天尝试Okta。 Netty是一个无阻塞的输入/输出&#xff08;NIO&#xff09;框架&#xff0c;它使开发低级网络服务器和客户端变得相对…

编辑器中代码中多行注释

1 Sublime 快捷键为ctl shift / ,并在第二行打一个*后&#xff0c;以后的换行会自动在开始打印一个* 2 VScode 快捷键为Alt Shift A,并在第二行与第三行分别开始打一个*后&#xff0c;以后的换行会自动在开始打印一个* 3 两者最通用的方式 使用快捷键后&#xff0c;在…

到无限(溪流)和超越!

Java允许您处理集合或流中的数据。 将流视为将一个集合转换为另一个集合的技术非常容易。 这可能会导致一些相当随意的代码&#xff0c;在该代码中&#xff0c;流数据被重复收集到某种类型的集合中&#xff0c;作为整体集合传递&#xff0c;然后再进行更多处理。 对于6个元素&…

PicGo {“message“:“A file with this name already exists“}解决方案

这里主要是重复上传了同类型的文件导致的冲突 1、打开PicGo 2、点击并打开PicGo设置 3、将“时间戳重命名”打开 4、从新上传测试一遍就可以了 结语 用时间戳给图片命名是避免文件重复的好方式&#xff0c;推荐设置

hadoop的开发工具_Hadoop开发工具简介

hadoop的开发工具几天前&#xff0c; Apache Hadoop开发工具 &#xff08;又名HDT &#xff09;发布了。 这些项目旨在将插件引入eclipse中&#xff0c;以简化Hadoop平台上的开发。 该博客旨在概述HDT的一些重要功能。 单端点 该项目可以充当HDFS&#xff0c;Zookeeper和MR群集…