![](http://img.szonline.cn/2022/1118/20221118104248143.jpg)
Spring 集成是數(shù)據(jù)的通用容器。 任何對(duì)象都可以作為有效負(fù)載提供,每個(gè)實(shí)例都包含包含用戶可擴(kuò)展屬性作為鍵值對(duì)的標(biāo)頭。??Message?
???Message?
?
?Message?
?以下清單顯示了接口的定義:??Message?
?
public interface Message{ T getPayload(); MessageHeaders getHeaders();}
接口是 API 的核心部分。 通過將數(shù)據(jù)封裝在通用包裝器中,郵件系統(tǒng)可以在不了解數(shù)據(jù)類型的情況下傳遞數(shù)據(jù)。 隨著應(yīng)用程序發(fā)展到支持新類型,或者當(dāng)類型本身被修改或擴(kuò)展時(shí),郵件系統(tǒng)不受影響。 另一方面,當(dāng)消息傳遞系統(tǒng)中的某些組件確實(shí)需要訪問有關(guān)的信息時(shí),此類元數(shù)據(jù)通常可以存儲(chǔ)到消息頭中的元數(shù)據(jù)并從中檢索。??Message?
???Message?
?
【資料圖】
正如Spring Integration允許any用作a的有效載荷一樣,它也支持anytype作為標(biāo)頭值。 實(shí)際上,該類實(shí)現(xiàn)了,如以下類定義所示:??Object?
???Message?
???Object?
???MessageHeaders?
???java.util.Map_ interface?
?
public final class MessageHeaders implements Map, Serializable { ...}
即使類實(shí)現(xiàn)了,它實(shí)際上也是一個(gè)只讀實(shí)現(xiàn)。 映射中的任何嘗試 to 值都會(huì)導(dǎo)致 an. 這同樣適用于。 由于消息可以傳遞給多個(gè)消費(fèi)者,因此無法修改其結(jié)構(gòu)。 同樣,消息的有效負(fù)載不能在初始創(chuàng)建之后。 但是,標(biāo)頭值本身(或有效負(fù)載對(duì)象)的可變性有意留給框架用戶決定。? |
作為實(shí)現(xiàn),可以通過調(diào)用標(biāo)頭的名稱來檢索標(biāo)頭。 或者,您可以提供預(yù)期作為附加參數(shù)。 更好的是,當(dāng)檢索預(yù)定義的值之一時(shí),可以使用方便的吸氣器。 以下示例分別顯示了這三個(gè)選項(xiàng):??Map?
???get(..)?
???Class?
?
Object someValue = message.getHeaders().get("someKey");CustomerId customerId = message.getHeaders().get("customerId", CustomerId.class);Long timestamp = message.getHeaders().getTimestamp();
下表描述了預(yù)定義的消息標(biāo)頭:
表 1.預(yù)定義的消息頭
標(biāo)頭名稱 | 標(biāo)頭類型 | 用法 |
MessageHeaders.ID | java.util.UUID | 此消息實(shí)例的標(biāo)識(shí)符。 每次消息發(fā)生突變時(shí)都會(huì)更改。 |
MessageHeaders.TIMESTAMP | java.lang.Long | 創(chuàng)建消息的時(shí)間。 每次消息發(fā)生突變時(shí)都會(huì)更改。 |
MessageHeaders.REPLY_CHANNEL | java.lang.Object(String orMessageChannel) | 在未配置顯式輸出通道且沒有或已用盡時(shí)向其發(fā)送回復(fù)(如果有)的通道。 如果值為 a,則它必須表示 Bean 名稱或由? |
MessageHeaders.ERROR_CHANNEL | java.lang.Object(String orMessageChannel) | 將錯(cuò)誤發(fā)送到的通道。 如果值為 a,則它必須表示 Bean 名稱或由? |
許多入站和出站適配器實(shí)現(xiàn)還提供或需要某些標(biāo)頭,您可以配置其他用戶定義的標(biāo)頭。 這些標(biāo)頭的常量可以在存在此類標(biāo)頭的模塊中找到,例如,,等等。??AmqpHeaders?
???JmsHeaders?
?
?MessageHeaderAccessor?
?應(yīng)用程序接口從 Spring Framework 4.0 和 Spring Integration 4.0 開始,核心消息傳遞抽象已移至模塊,并引入了 API 以提供對(duì)消息傳遞實(shí)現(xiàn)的額外抽象。 所有(核心)Spring 集成特定的消息頭常量現(xiàn)在都在類中聲明。 下表描述了預(yù)定義的消息標(biāo)頭:??spring-messaging?
???MessageHeaderAccessor?
???IntegrationMessageHeaderAccessor?
?
表 2.預(yù)定義的消息頭
標(biāo)頭名稱 | 標(biāo)頭類型 | 用法 |
IntegrationMessageHeaderAccessor.CORRELATION_ID | java.lang.Object | 用于關(guān)聯(lián)兩條或多條消息。 |
IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER | java.lang.Integer | 通常,帶有一組帶有 abut 的消息的序列號(hào)也可用于 ato 對(duì)無限的消息組重新排序。? |
IntegrationMessageHeaderAccessor.SEQUENCE_SIZE | java.lang.Integer | 一組相關(guān)消息中的消息數(shù)。 |
IntegrationMessageHeaderAccessor.EXPIRATION_DATE | java.lang.Long | 指示消息何時(shí)過期。 不直接由框架使用,但可以使用標(biāo)頭擴(kuò)充器進(jìn)行設(shè)置,并在配置了 an 的 a 中使用。? |
IntegrationMessageHeaderAccessor.PRIORITY | java.lang.Integer | 消息優(yōu)先級(jí) — 例如,在 a 中。? |
IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE | java.lang.Boolean | 如果消息被冪等接收方攔截器檢測為重復(fù),則為 True。 請(qǐng)參閱冪等接收器企業(yè)集成模式。 |
IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE | java.io.Closeable | 如果消息與消息處理完成后應(yīng)關(guān)閉的 關(guān)聯(lián),則存在此標(biāo)頭。 例如,與使用 FTP、SFTP 等的流文件傳輸相關(guān)聯(lián)。? |
IntegrationMessageHeaderAccessor.DELIVERY_ATTEMPT | java.lang.AtomicInteger | 如果消息驅(qū)動(dòng)的通道適配器支持 a 的配置,則此標(biāo)頭包含當(dāng)前傳遞嘗試。? |
IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK | o.s.i.support.AcknowledgmentCallback | 如果入站終端節(jié)點(diǎn)支持,則回調(diào)以接受、拒絕或重新排隊(duì)消息。 請(qǐng)參閱延遲確認(rèn)可輪詢消息源?和??MQTT 手動(dòng)確認(rèn)??。 |
類中提供了其中一些標(biāo)頭的方便的類型化 getter,如以下示例所示:??IntegrationMessageHeaderAccessor?
?
IntegrationMessageHeaderAccessor accessor = new IntegrationMessageHeaderAccessor(message);int sequenceNumber = accessor.getSequenceNumber();Object correlationId = accessor.getCorrelationId();...
下表描述了也出現(xiàn)在 但是 通常不被用戶代碼使用的標(biāo)頭(也就是說,它們通常由 Spring 集成的內(nèi)部部分使用 — 為了完整起見,此處包含它們):??IntegrationMessageHeaderAccessor?
?
表 3.預(yù)定義的消息頭
標(biāo)頭名稱 | 標(biāo)頭類型 | 用法 |
IntegrationMessageHeaderAccessor.SEQUENCE_DETAILS | java.util.List | 需要嵌套相關(guān)性時(shí)使用的相關(guān)數(shù)據(jù)堆棧(例如,)。? |
IntegrationMessageHeaderAccessor.ROUTING_SLIP | java.util.Map | 請(qǐng)參閱傳送名單。 |
當(dāng)消息通過應(yīng)用程序轉(zhuǎn)換時(shí),每次它都會(huì)發(fā)生突變(例如, 通過轉(zhuǎn)換器)分配一個(gè)新的消息 ID。 消息 ID 為 a。 從 Spring Integration 3.0 開始,用于 IS 生成的默認(rèn)策略比以前的實(shí)現(xiàn)更有效。 它使用基于安全隨機(jī)種子的簡單隨機(jī)數(shù),而不是每次都創(chuàng)建安全隨機(jī)數(shù)。??UUID?
???java.util.UUID.randomUUID()?
?
可以通過聲明在應(yīng)用程序上下文中實(shí)現(xiàn)的 Bean 來選擇不同的 UUID 生成策略。??org.springframework.util.IdGenerator?
?
類裝入器中只能使用一個(gè) UUID 生成策略。 這意味著,如果兩個(gè)或多個(gè)應(yīng)用程序上下文在同一個(gè)類裝入器中運(yùn)行,它們將共享相同的策略。 如果其中一個(gè)上下文更改了策略,則所有上下文都會(huì)使用該上下文。 如果同一類裝入器中的兩個(gè)或多個(gè)上下文聲明了類型的 Bean,則它們都必須是同一類的實(shí)例。 否則,嘗試替換自定義策略的上下文將無法初始化。 如果策略相同,但已參數(shù)化,則使用要初始化的第一個(gè)上下文中的策略。? |
除了默認(rèn)策略之外,還提供了兩個(gè)額外的策略。使用以前的機(jī)制。 當(dāng)不需要 UUID 并且簡單的遞增值就足夠時(shí),您可以使用。??IdGenerators?
???org.springframework.util.JdkIdGenerator?
???UUID.randomUUID()?
???o.s.i.support.IdGenerators.SimpleIncrementingIdGenerator?
?
Theand是只讀標(biāo)頭,不能被覆蓋。??MessageHeaders.ID?
???MessageHeaders.TIMESTAMP?
?
從版本 4.3.2 開始,提供了 API 來自定義不應(yīng)從上游復(fù)制的標(biāo)頭列表。 默認(rèn)情況下,只有 theand是只讀的。 提供全局屬性(請(qǐng)參閱全局屬性)是為了自定義框架組件。 當(dāng)您不想填充一些現(xiàn)成的標(biāo)頭時(shí),這可能很有用,例如JSON 轉(zhuǎn)換器。??MessageBuilder?
???readOnlyHeaders(String… readOnlyHeaders)?
???Message?
???MessageHeaders.ID?
???MessageHeaders.TIMESTAMP?
???spring.integration.readOnly.headers?
???DefaultMessageBuilderFactory?
???contentType?
???ObjectToJsonTransformer?
?
當(dāng)您嘗試使用 構(gòu)建新消息時(shí),將忽略此類標(biāo)頭,并向日志發(fā)出特定消息。??MessageBuilder?
???INFO?
?
從版本 5.0 開始,消息網(wǎng)關(guān)、標(biāo)頭擴(kuò)充器、內(nèi)容擴(kuò)充器和標(biāo)頭篩選器不允許您在使用時(shí)配置 andheader 名稱,并且它們會(huì)拋出。??MessageHeaders.ID?
???MessageHeaders.TIMESTAMP?
???DefaultMessageBuilderFactory?
???BeanInitializationException?
?
通常,當(dāng)消息生成終結(jié)點(diǎn)(如服務(wù)激活器)處理(和修改)消息時(shí),入站標(biāo)頭將傳播到出站消息。 一個(gè)例外是轉(zhuǎn)換器,當(dāng)完整的消息返回到框架時(shí)。 在這種情況下,用戶代碼負(fù)責(zé)整個(gè)出站消息。 當(dāng)轉(zhuǎn)換器僅返回有效負(fù)載時(shí),將傳播入站標(biāo)頭。 此外,僅當(dāng)出站消息中尚不存在標(biāo)頭時(shí),才會(huì)傳播標(biāo)頭,從而允許您根據(jù)需要更改標(biāo)頭值。
從版本 4.3.10 開始,您可以配置消息處理程序(修改消息并生成輸出)以禁止特定標(biāo)頭的傳播。 要配置您不想復(fù)制的標(biāo)頭,請(qǐng)?jiān)诔橄箢惿险{(diào)用 theormethods。??setNotPropagatedHeaders()?
???addNotPropagatedHeaders()?
???MessageProducingMessageHandler?
?
還可以通過將屬性設(shè)置為逗號(hào)分隔的標(biāo)頭列表來全局禁止特定消息標(biāo)頭的傳播。??readOnlyHeaders?
???META-INF/spring.integration.properties?
?
從版本 5.0 開始,上的實(shí)現(xiàn)應(yīng)用簡單的模式 (,??,*xxx?
?或) 以允許過濾具有通用后綴或前綴的標(biāo)頭。 參見PatternMatchUtilsJavadoc了解更多信息。 當(dāng)其中一個(gè)模式為(星號(hào))時(shí),不會(huì)傳播任何標(biāo)頭。 忽略所有其他模式。 在這種情況下,服務(wù)激活器的行為方式與轉(zhuǎn)換器相同,并且必須從服務(wù)方法中提供任何所需的標(biāo)頭。 該選項(xiàng)在Java DSL中可用 它也可用于組件的XML配置作為屬性。??setNotPropagatedHeaders()?
???AbstractMessageProducingHandler?
???xxx*?
???xxx?
???xxx*yyy?
???*?
???Message?
???notPropagatedHeaders()?
???ConsumerEndpointSpec?
???
???not-propagated-headers?
?
標(biāo)頭傳播抑制不適用于不修改消息的終結(jié)點(diǎn),例如網(wǎng)橋?和路由器。 |
接口的基本實(shí)現(xiàn)是,它提供了兩個(gè)構(gòu)造函數(shù),如以下清單所示:??Message?
???GenericMessage
?
new GenericMessage(T payload);new GenericMessage (T payload, Map headers)
創(chuàng)建 ais 時(shí),會(huì)生成一個(gè)隨機(jī)的唯一 ID。 接受 aof 標(biāo)頭的構(gòu)造函數(shù)將提供的標(biāo)頭復(fù)制到新創(chuàng)建的標(biāo)頭。??Message?
???Map?
???Message?
?
還有一個(gè)方便的實(shí)現(xiàn)設(shè)計(jì)用于傳達(dá)錯(cuò)誤條件。 此實(shí)現(xiàn)將對(duì)象作為其有效負(fù)載,如以下示例所示:??Message?
???Throwable?
?
ErrorMessage message = new ErrorMessage(someThrowable);Throwable t = message.getPayload();
請(qǐng)注意,此實(shí)現(xiàn)利用了基類參數(shù)化的事實(shí)。 因此,如兩個(gè)示例所示,檢索有效負(fù)載時(shí)不需要強(qiáng)制轉(zhuǎn)換。??GenericMessage?
???Message?
???Object?
?
?MessageBuilder?
?您可能會(huì)注意到,該接口為其有效負(fù)載和標(biāo)頭定義了檢索方法,但沒有提供資源庫。 這樣做的原因是 a 在初始創(chuàng)建后無法修改。 因此,當(dāng)將實(shí)例發(fā)送給多個(gè)使用者時(shí)(例如, 通過發(fā)布-訂閱通道),如果其中一個(gè)使用者需要使用不同的有效負(fù)載類型發(fā)送回復(fù),則必須創(chuàng)建一個(gè)新的。 因此,其他使用者不受這些更改的影響。 請(qǐng)記住,多個(gè)使用者可以訪問相同的有效負(fù)載實(shí)例或標(biāo)頭值,并且此類實(shí)例本身是否不可變是留給您的決定。 換句話說,契約類似于不可修改的契約,地圖進(jìn)一步說明了這一點(diǎn)。 即使 theclass 實(shí)現(xiàn)了,任何在實(shí)例上調(diào)用操作(或“刪除”或“清除”)的嘗試都會(huì)導(dǎo)致 an。??Message?
???Message?
???Message?
???Message?
???Message?
???Collection?
???MessageHeaders?
???MessageHeaders?
???java.util.Map?
???put?
???MessageHeaders?
???UnsupportedOperationException?
?
Spring Integration 不需要將 Map 的創(chuàng)建和填充傳遞到 GenericMessage 構(gòu)造函數(shù)中,而是提供了一種更方便的構(gòu)造 Messages: 的方法。 提供了兩種工廠方法,用于從具有有效負(fù)載的現(xiàn)有實(shí)例或創(chuàng)建實(shí)例。 從現(xiàn)有構(gòu)建時(shí),其標(biāo)頭和有效負(fù)載將復(fù)制到新文件,如以下示例所示:??MessageBuilder?
???MessageBuilder?
???Message?
???Message?
???Object?
???Message?
???Message?
???Message?
?
Messagemessage1 = MessageBuilder.withPayload("test") .setHeader("foo", "bar") .build();Message message2 = MessageBuilder.fromMessage(message1).build();assertEquals("test", message2.getPayload());assertEquals("bar", message2.getHeaders().get("foo"));
如果您需要使用新的有效負(fù)載創(chuàng)建 a,但仍想從現(xiàn)有負(fù)載復(fù)制標(biāo)頭,則可以使用“copy”方法之一,如以下示例所示:??Message?
???Message?
?
Messagemessage3 = MessageBuilder.withPayload("test3") .copyHeaders(message1.getHeaders()) .build();Message message4 = MessageBuilder.withPayload("test4") .setHeader("foo", 123) .copyHeadersIfAbsent(message1.getHeaders()) .build();assertEquals("bar", message3.getHeaders().get("foo"));assertEquals(123, message4.getHeaders().get("foo"));
請(qǐng)注意,該方法不會(huì)覆蓋現(xiàn)有值。 此外,在前面的示例中,您可以看到如何使用 設(shè)置任何用戶定義的標(biāo)頭。 最后,有可用于預(yù)定義標(biāo)頭的方法以及用于設(shè)置任何標(biāo)頭的非破壞性方法(也為預(yù)定義標(biāo)頭名稱定義常量)。??copyHeadersIfAbsent?
???setHeader?
???set?
???MessageHeaders?
?
您還可以用于設(shè)置消息的優(yōu)先級(jí),如以下示例所示:??MessageBuilder?
?
MessageimportantMessage = MessageBuilder.withPayload(99) .setPriority(5) .build();assertEquals(5, importantMessage.getHeaders().getPriority());Message lessImportantMessage = MessageBuilder.fromMessage(importantMessage) .setHeaderIfAbsent(IntegrationMessageHeaderAccessor.PRIORITY, 2) .build();assertEquals(2, lessImportantMessage.getHeaders().getPriority());
只有在使用 a(如下一章所述)時(shí)才考慮標(biāo)頭。 它被定義為 a。??priority?
???PriorityChannel?
???java.lang.Integer?
?
標(biāo)簽: 有效負(fù)載 應(yīng)用程序 消息傳遞