javascript
corda_使用Spring WebFlux从Corda节点流式传输数据
corda
自上次發(fā)布以來已經(jīng)有一段時(shí)間了,但我終于回來了! 由于我仍在我的項(xiàng)目中,因此我將再次撰寫有關(guān)使用Corda的文章。 這次,我們將不再關(guān)注Corda,而是將Spring與Corda結(jié)合使用。 更具體地說,Spring WebFlux。 為什么這樣 第一,因?yàn)槲覀兛梢浴?第二,因?yàn)樗试S我們流式傳輸來自Corda節(jié)點(diǎn)的事件。 這使我們能夠跟蹤流的進(jìn)度或檢索對(duì)Vault的更新,并將其發(fā)送給注冊(cè)到相關(guān)端點(diǎn)的任何客戶端。 將WebFlux與Corda結(jié)合使用確實(shí)會(huì)帶來一些問題。 有些來自Corda,有些來自Spring。 雖然,Spring問題與我有關(guān),但我期望Spring Boot + WebFlux組合默認(rèn)對(duì)我有更多作用。
在這篇文章中,我假設(shè)您對(duì)Corda有一定的經(jīng)驗(yàn),但是如果您確實(shí)需要有關(guān)Corda的一些信息,我建議您閱讀我以前的文章: 什么是Corda和Corda 開發(fā) 。 此外,我還建議您看一下使用Spring WebFlux做事,作為WebFlux的介紹。
本教程的內(nèi)容將使用Corda的3.2開源版本。 我實(shí)際上是根據(jù)3.1開始寫這篇文章的,但是在此期間發(fā)布了較新的版本。 因此,有一些基于在這些版本之間移動(dòng)的注釋。
我們還將在Kotlin中實(shí)現(xiàn)所有內(nèi)容,但本文的內(nèi)容也可以在Java中實(shí)現(xiàn)。
示例應(yīng)用程序簡(jiǎn)介
我們將為一個(gè)非常簡(jiǎn)單的應(yīng)用程序建模,該應(yīng)用程序不會(huì)提供太多使用,因此,出于這篇文章的目的,我將它們一起打包。 該應(yīng)用程序?qū)⒂梢粋€(gè)發(fā)送方(由MessageState表示)的一方發(fā)送給另一方。 為此, SendMessageFlow將運(yùn)行,一旦運(yùn)行,雙方將擁有消息的副本,僅此而已。 簡(jiǎn)短而簡(jiǎn)單,但應(yīng)為我們提供足夠的知識(shí)來證明WebFlux如何與Corda配合使用。
結(jié)構(gòu)體
通常,我從查看依賴關(guān)系開始。 盡管由于將代碼分成了單獨(dú)的模塊,所以最好先查看小示例應(yīng)用程序的結(jié)構(gòu)。
+-- app | +-- {spring code} | +-- build.gradle +-- cordapp | +-- {flow code} | +-- build.gradle +-- contracts-and-states | +-- {contracts and states code} | +-- build.gradle +-- build.gradle這是應(yīng)用程序結(jié)構(gòu)的快速視圖。 app將包含所有Spring代碼,并將通過RPC委托給Corda節(jié)點(diǎn)。 cordapp模塊包含流邏輯, contracts-and-states按照名稱的建議進(jìn)行操作,并包含契約和狀態(tài)代碼。 cordapp模塊和contracts-and-states模塊都打包到Cordapp Jars中,并轉(zhuǎn)儲(chǔ)到Corda節(jié)點(diǎn)中。
這些模塊中的每個(gè)模塊都包含一個(gè)build.gradle文件,該文件包含其相關(guān)的構(gòu)建信息和相關(guān)性。 由于本文不是直接著眼于編寫Corda代碼,因此我們將不繼續(xù)詳細(xì)研究每個(gè)模塊及其構(gòu)建文件。 取而代之的是,我們僅在帖子末尾重新整理流代碼,以便我們專注于Spring實(shí)現(xiàn)。
Spring模塊的依賴
以下是app模塊的build.gradle文件(包含Spring代碼):
我不是Gradle的專家,因此該代碼段中可能有一些可以做得更好的事情,但它確實(shí)可以做到。
因此,我想強(qiáng)調(diào)一些事情。 使用Spring Boot 2.0.3.RELEASE并與此kotlin-spring使用,使用kotlin-spring插件向所有標(biāo)有某些Spring注釋的Kotlin類添加open 。 這在很多情況下都是必需的,因?yàn)镾pring要求某些類是非最終的。 這在Java中不是問題,但對(duì)于Kotlin來說是有問題的,因?yàn)槟J(rèn)情況下所有類都是final。 有關(guān)該插件的更多信息,請(qǐng)?jiān)L問kotlinlang.org 。
spring-boot-starter-webflux了WebFlux依賴關(guān)系以及常規(guī)的Spring Web服務(wù)器代碼,以使一切正常運(yùn)行。
rxjava-reactive-streams ,這是一個(gè)有趣的問題,稍后我們將看到它的作用。 由于Corda使用RxJava 1.xx而非較新的RxJava2,因此其Observable不會(huì)實(shí)現(xiàn)Spring WebFlux用于返回React流的Java 8 Publisher接口。 此依賴關(guān)系將這些較舊的Observable轉(zhuǎn)換為Publisher因此它們與WebFlux兼容。 我們稍后會(huì)在查看代碼進(jìn)行轉(zhuǎn)換時(shí)再次談到。
最后, netty-all版本被強(qiáng)制為4.1.25.Final以解決依賴關(guān)系問題。
路由功能
WebFlux引入了一種功能性方法,用于將請(qǐng)求路由到處理請(qǐng)求的功能。 有關(guān)更多信息,請(qǐng)參見使用Spring WebFlux進(jìn)行操作 。 我不想深入探討WebFlux的工作方式,但我們將快速定義路由功能。 主要原因是由于使用Kotlin而不是Java。 Kotlin提供了使用DSL定義功能的另一種方法。
以下是定義本教程路由的代碼:
routes bean接收MessageHandler bean(我們將在后面進(jìn)行討論)并將兩個(gè)URI映射到該MessageHandler找到的函數(shù)。 與Java實(shí)現(xiàn)相比,DSL允許的版本略短。 此片段中有幾個(gè)部分需要重點(diǎn)關(guān)注。
("/messages")定義兩個(gè)路由功能的基本請(qǐng)求路徑。 DSL允許功能從此基本路徑嵌套自己,并幫助傳達(dá)路線的結(jié)構(gòu)。
一個(gè)函數(shù)在發(fā)送請(qǐng)求后返回的響應(yīng)中接受TEXT_EVENT_STREAM ( text/event-stream ),同時(shí)還將APPLICATION_JSON ( application/stream+json )指定為正文的內(nèi)容。 由于我們已經(jīng)定義了Content-Type ,因此在大多數(shù)情況下,我們可以假設(shè)我們將發(fā)送一個(gè)POST請(qǐng)求(就是這樣)。 POST從以前的配置中進(jìn)一步嵌套,并添加了另一個(gè)MessageHandler函數(shù)來接受請(qǐng)求。
第二個(gè)功能從Corda節(jié)點(diǎn)接收更新。 為此,它返回APPLICATION_STREAM_JSON并期望將GET請(qǐng)求發(fā)送到/messages/updates 。
處理函數(shù)
在本節(jié)中,我們將看一下上一節(jié)中幾次提到的MessageHandler 。 此類包含執(zhí)行實(shí)際業(yè)務(wù)邏輯的所有功能。 路由只是達(dá)到這一點(diǎn)的一種方法。
我以前的文章“用Spring WebFlux做事”將比本文更深入地解釋這些示例中更多WebFlux的特定部分。
下面是處理程序代碼:
首先,我們應(yīng)突出顯示NodeRPCConnection類及其類型為CordaRPCOps的屬性proxy 。 我從示例Corda和Spring應(yīng)用程序 (由R3員工編寫)中竊取了NodeRPCConnection 。 長(zhǎng)話短說, NodeRPCConnection創(chuàng)建到Corda節(jié)點(diǎn)的RPC連接,并且proxy返回CordaRPCOps 。 CordaRPCOps包含所有可用的RPC操作。 這就是Spring與Corda節(jié)點(diǎn)交互的方式。
讓我們仔細(xì)看看updates功能:
此功能返回新消息,將其保存到Vault中。 如果您有一個(gè)監(jiān)視來自Corda節(jié)點(diǎn)的更新的應(yīng)用程序,則這種端點(diǎn)非常有用。
此代碼段中與Corda相關(guān)的代碼全部包含在trackNewMessages函數(shù)中。 它使用CordaRPCOps的vaultTrackBy訪問保管庫服務(wù),并開始跟蹤對(duì)任何MessageState的更新。 由于我們尚未將任何參數(shù)傳遞給該函數(shù),因此它將僅跟蹤UNCONSUMED狀態(tài)。 vaultTrackBy返回一個(gè)DataFeed對(duì)象, DataFeed對(duì)象可以用于通過snapshot屬性檢索保管庫的snapshot也可以通過訪問updates屬性來返回一個(gè)Observable以允許其訂閱更新事件。 這個(gè)RxJava Observable是我們用來將數(shù)據(jù)流回調(diào)用者的工具。
這是我們需要使用我前面提到的rxjava-reactive-streams的第一個(gè)實(shí)例。 toPublisher方法接受一個(gè)Observable并將其轉(zhuǎn)換為Publisher 。 請(qǐng)記住,WebFlux需要Java 8兼容的React式流庫,這些庫必須實(shí)現(xiàn)Publisher 。 例如,Spring傾向于使用提供Mono和Flux類的Reactor 。
創(chuàng)建Publisher ,需要將其饋送到ServerResponse 。 由于目前一切順利,我們將通過ok方法返回200響應(yīng)。 然后將Content-Type設(shè)置為APPLICATION_STREAM_JSON因?yàn)樗鲾?shù)據(jù)。 最后,響應(yīng)的主體從trackNewMessages中獲取Publisher trackNewMessages 。 現(xiàn)在,端點(diǎn)已準(zhǔn)備好由發(fā)出請(qǐng)求的客戶端進(jìn)行訂閱。
現(xiàn)在,完成了從節(jié)點(diǎn)到客戶端的流更新功能。 實(shí)際保存新消息怎么辦? 此外,是否有任何信息可以傳遞給發(fā)送者有關(guān)執(zhí)行流程的信息? 因此,讓我們回答這兩個(gè)問題。 是的,我們可以使用WebFlux保存新消息。 是的,流程可以返回其當(dāng)前進(jìn)度。
下面是post函數(shù)的代碼,該函數(shù)在流的流進(jìn)度時(shí)將新消息保存到發(fā)件人和收件人的節(jié)點(diǎn)上:
proxy.startTrackedFlow啟動(dòng)一個(gè)流程,該流程的進(jìn)度可以由添加到該流程的任何ProgressTracker跟蹤。 此類中定義的startTrackedFlow委托給上述函數(shù),并返回其progress屬性; 一個(gè)Observable<String>其事件由ProgressTracker的進(jìn)度組成。
傳遞到流中的MessageState是從請(qǐng)求傳遞的Message對(duì)象創(chuàng)建的。 這是因?yàn)樗男畔⒈萂essageState本身少,因此可以更輕松地將消息數(shù)據(jù)輸入到端點(diǎn)。 parse將Message傳遞的字符串X500名稱轉(zhuǎn)換為CordaX500Name ,然后假定存在網(wǎng)絡(luò)中,轉(zhuǎn)換為網(wǎng)絡(luò)中的Party 。
然后通過created方法將其打包到響應(yīng)中。 指定Content-Type來告訴客戶端它包含text/event-stream 。 消息的路徑使用在執(zhí)行流之前創(chuàng)建的UUID 。 例如,這可以用于檢索特定的消息,但是您需要自己實(shí)現(xiàn)該消息,因?yàn)槲姨珣辛?#xff0c;因此本文不做。
創(chuàng)建一個(gè)客戶
現(xiàn)在已經(jīng)設(shè)置了端點(diǎn),我們應(yīng)該創(chuàng)建一個(gè)可以發(fā)送請(qǐng)求并使用發(fā)送回它的流的客戶端。 稍后,我們將簡(jiǎn)要地看一下流代碼,以更全面地了解正在發(fā)生的事情。
為了將請(qǐng)求發(fā)送到響應(yīng)式后端,Spring WebFlux提供了WebClient類。 發(fā)送請(qǐng)求后, WebClient可以對(duì)響應(yīng)中發(fā)送的每個(gè)事件做出React。 下面的MessageClient就是這樣做的:
MessageClient包裝并使用WebClient將請(qǐng)求發(fā)送到WebClient的構(gòu)建器中指定的地址。 在該課程中,關(guān)于反序列化還有一些額外的配置,但是我想暫時(shí)重新介紹一下,因?yàn)檫€有一部分內(nèi)容涉及該主題。
和以前一樣, 使用Spring WebFlux做事提供了WebFlux特定方法的深入解釋。
因此,讓我們單獨(dú)查看每個(gè)請(qǐng)求,首先將POST請(qǐng)求發(fā)送到/messages端點(diǎn):
post方法創(chuàng)建一個(gè)用于指定請(qǐng)求內(nèi)容的構(gòu)建器。 這應(yīng)該與我們之前定義的端點(diǎn)匹配。 建立請(qǐng)求后,請(qǐng)調(diào)用exchange方法將其發(fā)送到服務(wù)器。 然后將響應(yīng)的主體映射到Flux<String> ,以使其可以訂閱。 那就是使用React流的本質(zhì)。 訂閱響應(yīng)后,客戶端將決定對(duì)每個(gè)事件執(zhí)行他們希望執(zhí)行的任何處理。 在這種情況下,它只是打印出ProgressTracker的當(dāng)前步驟。
如果我們通過這段代碼發(fā)送請(qǐng)求,我們將收到以下信息:
STEP: Verifying STEP: Signing STEP: Sending to Counterparty STEP: Collecting signatures from counterparties. STEP: Verifying collected signatures. STEP: Done STEP: Finalising STEP: Requesting signature by notary service STEP: Broadcasting transaction to participants STEP: Done STEP: Done這些是SendMessageFlow的ProgressTracker定義的步驟。 是的,我知道我還沒有向您顯示該代碼,但是請(qǐng)相信我。 真的沒有太多其他。 如您所見,流返回的每個(gè)字符串值都將“ STEP”附加到自身
現(xiàn)在進(jìn)入到/messages/update端點(diǎn)的GET請(qǐng)求:
同樣,在這一點(diǎn)上沒有什么可顯示的。 但是,在幕后,實(shí)際上需要大量工作才能使它工作。 我需要打通電話才能解決的所有問題都圍繞著序列化和反序列化。 我們將在下一部分中進(jìn)行介紹。
對(duì)此請(qǐng)求的響應(yīng)如下:
UPDATE: 0 consumed, 1 producedConsumed:Produced: 56781DF3CEBF2CDAFACE1C5BF04D4962B5483FBCD2C2E428352AD82BC951C686(0) : TransactionState(data=MessageState(sender=O=PartyA, L=London, C=GB, recipient=O=PartyB, L=London, C=GB, contents=hello there, linearId=1afc6144-32b1-4265-a06e-73b6bb81aef3_b0fa8491-c9b9-418c-ba6e-8b7840faaf30, participants=[O=PartyA, L=London, C=GB, O=PartyB, L=London, C=GB]), contract=com.lankydanblog.tutorial.contracts.MessageContract, notary=O=Notary, L=London, C=GB, encumbrance=null, constraint=net.corda.core.contracts.WhitelistedByZoneAttachmentConstraint@4a1febb5)關(guān)于此端點(diǎn)的好處是,它現(xiàn)在與節(jié)點(diǎn)保持連接,該節(jié)點(diǎn)將繼續(xù)將所有相關(guān)更新發(fā)送回此客戶端。 上面的請(qǐng)求是原始POST消息的更新。 客戶端收到的任何新事件都會(huì)在客戶端上輸出更新。 這就是使此類端點(diǎn)非常適合觸發(fā)進(jìn)程或僅在與Corda節(jié)點(diǎn)本身分開的前端上顯示最新數(shù)據(jù)的理想之選。
序列化和反序列化
在本節(jié)中,我想集中精力正確設(shè)置序列化和反序列化。 從/messages/updates端點(diǎn)檢索到的數(shù)據(jù)需要正確地序列化其數(shù)據(jù),以傳遞給客戶端,客戶端也需要能夠反序列化響應(yīng)數(shù)據(jù)。
通常,Spring會(huì)為您做很多事情,而且仍然會(huì)做,但是WebFlux似乎需要一些額外的步驟才能正確設(shè)置它。 免責(zé)聲明,這是根據(jù)我的經(jīng)驗(yàn),如果您知道執(zhí)行此操作的更好方法,我將很高興收到您的來信。
Corda Jackson支持
Spring默認(rèn)情況下傾向于使用Jackson,并且很方便地,Corda本身提供了很多Jackson設(shè)置。 JacksonSupport.cordaModule為諸如Party和CordaX500Name類的類提供了一些序列化和反序列化。 如果在某些基本情況下需要對(duì)Corda類進(jìn)行序列化或反序列化,則這可能會(huì)滿足您的需求。 在Spring中,您可以創(chuàng)建一個(gè)默認(rèn)的ObjectMapper將檢索并添加到其自身的bean。
但是,此路線有一些警告。 由于模塊依賴于ObjectMapper可以訪問節(jié)點(diǎn)信息,例如通過RPC客戶端CordaRPCOps訪問節(jié)點(diǎn)信息,因此無法反序列化某些類。 否則,反序列化Party , AbstractParty或AnonymousParty將會(huì)失敗。 不僅如此,由于不安全,此功能現(xiàn)已從Corda 3.2棄用。 JacksonSupport.cordaModule也已移入其自己的類( CordaModule )。
我下面提供的解決方案也是Corda從現(xiàn)在開始建議采用的解決方案。
以下是MessageClient從/messages/updates端點(diǎn)檢索更新時(shí)引發(fā)的異常(對(duì)于本節(jié)的其余部分,將使用相同的端點(diǎn)):
com.fasterxml.jackson.databind.ObjectMapper cannot be cast to net.corda.client.jackson.JacksonSupport$PartyObjectMapper由此,我們可以確定我們的ObjectMapper類型錯(cuò)誤,并且實(shí)際上需要是PartyObjectMapper的子類型。 再進(jìn)一步,我們可以看到在JacksonSupport類中也找到了該映射器。 現(xiàn)在,剩下要做的就是創(chuàng)建這個(gè)映射器,并使用它而不是默認(rèn)的ObjectMapper 。
因此,讓我們看看如何做到這一點(diǎn):
這將創(chuàng)建一個(gè)RpcObjectMapper ,它實(shí)現(xiàn)PartyObjectMapper并利用RPC檢索節(jié)點(diǎn)信息,從而可以反序列化各種參與方類。 在createDefaultMapper, CordaModule了之前的CordaModule ,并感謝Spring,對(duì)于大多數(shù)需要序列化或反序列化的實(shí)例(以后要特別注意),它現(xiàn)在是默認(rèn)的對(duì)象映射器。
一些更多的序列化和反序列化配置
現(xiàn)在……我實(shí)際上處于一個(gè)很奇怪的位置。 我想通過所有其他步驟來使端點(diǎn)正常工作。 但是,無論我做什么,我似乎都無法重新創(chuàng)建曾經(jīng)遇到的所有錯(cuò)誤,然后才能使它起作用。 我不知道該說些什么……我的異常被吞沒在某處,阻止我看到正在發(fā)生的事情。 無論如何,我們必須繼續(xù)。 值得慶幸的是,我知道為什么我添加了其余的代碼,但我無法再為您提供每個(gè)更改都已修復(fù)的例外……
Soooo,讓我們看一下我們?cè)缦乳_始研究的rpcObjectMapper的最終產(chǎn)品:
這里有一些補(bǔ)充。 JsonComponentModule作為bean添加,以便它拾取定義的@JsonSerializer和@JsonDeserializer自定義組件(在其他類中)。 似乎即使將其作為模塊添加到映射器,如果要查找和注冊(cè)自定義JSON組件,它仍然需要?jiǎng)?chuàng)建bean本身。
接下來是MixinModule 。 此類解決了在反序列化Vault.Update和SecureHash時(shí)出現(xiàn)的問題。 讓我們仔細(xì)看看。
Mixin允許我們將Jackson注釋添加到類上,而實(shí)際上沒有訪問類本身的權(quán)限,這顯然是我們無法控制的,因?yàn)檫@是Corda代碼庫中的對(duì)象。 另一個(gè)選擇是將其添加到我們之前討論的CordaModule ,但這是CordaModule 。
Vault.Update需要此方法,是因?yàn)樗哂忻麨閕sEmpty的方法,該方法不能很好地與Jackson配合使用,Jackson感到困惑,并認(rèn)為isEmpty與一個(gè)名為empty的布爾字段匹配。 因此,當(dāng)將JSON反序列化回對(duì)象時(shí),它將嘗試為該字段傳遞一個(gè)值。
MixinModule本身只是一個(gè)類,其構(gòu)造函數(shù)將VaultUpdateMixin和SecureHashMixin添加到其自身中。 然后,映射器就像添加其他模塊一樣添加該模塊。 任務(wù)完成。
添加到VaultUpdateMixin的Jackson批注是@JsonIgnore ,這可以說明@JsonIgnore 。 序列化或反序列化時(shí), isEmpty函數(shù)將被忽略。
接下來是SecureHashMixin :
從3.1升級(jí)到3.2后,我已經(jīng)添加了此功能。 對(duì)我來說,似乎忘記了為SecureHash添加Mixin。 CordaModule包括用于SecureHash.SHA256序列化和反序列化,但不包括SecureHash 。 上面的代碼是從CordaModule復(fù)制和粘貼的, CordaModule一個(gè)類與Mixin綁定在一起。
包含此內(nèi)容后,將解決3.1和3.2之間的差異。
我想我會(huì)為此提出一個(gè)問題!
定制序列化器和反序列器
要序列化Vault.Update僅AttachmentConstraint接口需要它自己的自定義序列化程序:
HashAttachmentConstraint可談的,因?yàn)橹挥蠬ashAttachmentConstraint實(shí)際上有任何字段。 這與稍后反序列化器匹配,在反序列化器上讀取type JSON字段以確定創(chuàng)建哪個(gè)對(duì)象。
需要自定義反序列器的最后兩個(gè)類是ContractState和AttachmentContract (與之前的序列化程序匹配):
ContractStateDeserialiser是一個(gè)非常懶惰的實(shí)現(xiàn),因?yàn)樵诒窘坛讨袃H使用一種狀態(tài)。 AttachmentConstraintDeserialiser使用序列化程序中定義的type字段來確定應(yīng)將其轉(zhuǎn)換為AttachmentConstraint哪種實(shí)現(xiàn)。
WebFlux特定的配置
由于使用了WebFlux,本小節(jié)將介紹額外的必需配置。 您已經(jīng)在MessageClient看到了一些配置,但是還需要做一些額外的工作:
客戶端需要這個(gè)bean能夠反序列化application/stream+json以及響應(yīng)中返回的對(duì)象。
要使用配置中定義的Jackson2JsonDecoder ,必須指定WebClient的ExchangeStrategies 。 不幸的是,沒有編寫ExchangeStrategies類來拾取我們已經(jīng)創(chuàng)建的Jackson2JsonDecoder 。 我希望這種配置在默認(rèn)情況下可以工作,但是哦。 要添加ExchangeStrategies ,必須使用WebClient構(gòu)建器。 一旦完成,我們終于到了。 完成打包響應(yīng)的所有序列化以及從客戶端使用響應(yīng)序列的反序列化已完成。
總結(jié)了我希望在本文中介紹的所有與Spring相關(guān)的代碼。
快速了解Flow代碼
在結(jié)束之前,我將簡(jiǎn)要展示為完成本教程的目的而編寫的流程:
這是一個(gè)非常簡(jiǎn)單的流程,增加了一個(gè)ProgressTracker , /messages請(qǐng)求用于跟蹤流程的當(dāng)前狀態(tài)。 簡(jiǎn)而言之,此流程將傳遞給它的MessageState并將其發(fā)送給交易對(duì)手。 在流程中移動(dòng)時(shí), ProgressTracker將更新為相關(guān)步驟。 可以在Corda文檔中找到有關(guān)使用ProgressTracker更多文檔。
關(guān)閉時(shí)間
老實(shí)說,這比我想象的要長(zhǎng)得多,而且花了我的時(shí)間比我希望的要長(zhǎng)得多。
總之,Spring WebFlux提供了使用響應(yīng)流在響應(yīng)事件到達(dá)時(shí)進(jìn)行處理的功能。 當(dāng)與Corda一起使用時(shí),可以跟蹤流程的進(jìn)度,并可以保持持久的庫更新流,隨時(shí)準(zhǔn)備在它們到達(dá)時(shí)采取行動(dòng)。 為了充分利用Corda的WebFlux,我們還必須研究確保對(duì)象由服務(wù)器正確序列化,然后由客戶端反序列化,以便可以使用它們。 Lucky Corda確實(shí)提供了其中一些功能,但是缺少一兩個(gè)類或功能,因此我們需要確保使用提供的對(duì)象映射器來使用它們。 不幸的是,WebFlux需要比使用Spring模塊時(shí)通常所需要的更多的配置,但是沒有什么不能解決的。
這篇文章的其余代碼可以在我的GitHub上找到
如果您喜歡這篇文章,可以在@LankyDanDev的 Twitter上關(guān)注我,我在其中發(fā)布新帖子的更新(盡管最近它們的運(yùn)行速度有所降低)。
翻譯自: https://www.javacodegeeks.com/2018/07/streaming-data-corda-node-spring-webflux.html
corda
總結(jié)
以上是生活随笔為你收集整理的corda_使用Spring WebFlux从Corda节点流式传输数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 孝感门户网站电脑版(孝感市网站)
- 下一篇: gradle idea java ssm