2010-8-27
kimmking@163.com
2. 消息结构
Spring Integration中的Message是一个通用的数据容器,可以提供任何对象作为负载(payload),任何Message也可以包含一些带有用户扩展属性键值对的头部。
2.1 消息接口
下面是Message的接口定义:
public interface Message<T> {
T getPayload();
MessageHeaders getHeaders();
}
很明显,Message是一个非常重要的API。通过一个通用的包装封装数据,消息系统可以传递它到各处,而无需知道数据的类型。为一个新应用解决了添加各种新类型,或者当类型可以修改或(和)扩展,消息系统将不会被这些更改影响。另一方面,当消息系统中的一些组件需要访问Message中的信息,一些元数据可以从Message头中存取。
2.2 消息头
正如Spring Integration允许任何对象作为Message的负载,它也支持任何对象类型作为消息头值。事实上,MessageHeaders类实现了java.util.Map接口:
public final class MessageHeaders implements Map<String, Object>, Serializable {
...
}
注意:
尽管MessageHeaders实现了Map,它却是一个只读的实现。任何试图put一个值到Map的操作都会抛出一个UnsupportedOperationException异常。remove和clear操作也是一样的。因为Message可以被传递给多个消费者,所以Map的结构不能被修改。并且,Message负载对象在创建以后不能被set。However, the mutability of the header values themselves (or the payload Object) is intentionally left as a decision for the framework user.
作为Map的一个实现,通过调用get方法,传递消息头的名称作为参数,即可以获取相应的消息头。另外,可以提供一个Class类型的第二个参数。更甚至于,对于获取预定义的值,可以使用非常方便的getter。如下是上面三种情形的示例:
Object someValue = message.getHeaders().get("someKey");
CustomerId customerId = message.getHeaders().get("customerId", CustomerId.class);
Long timestamp = message.getHeaders().getTimestamp();
如下是预定义的消息头:
Table 2.1. Pre-defined Message Headers
Header Name
|
Header Type
|
ID
|
java.util.UUID
|
TIMESTAMP
|
java.lang.Long
|
EXPIRATION_DATE
|
java.lang.Long
|
CORRELATION_ID
|
java.lang.Object
|
REPLY_CHANNEL
|
java.lang.Object (can be a String or MessageChannel)
|
ERROR_CHANNEL
|
java.lang.Object (can be a String or MessageChannel)
|
SEQUENCE_NUMBER
|
java.lang.Integer
|
SEQUENCE_SIZE
|
java.lang.Integer
|
PRIORITY
|
MessagePriority (an enum)
|
很多inbound和outbound的adapter实现也提供或(和)期望适当的消息头,当然也可以配置额外的用户自定义消息头。
2.3 消息实现
Message接口的基本实现是GenericMessage<T>,他提供了两个构造器:
new GenericMessage<T>(T payload);
new GenericMessage<T>(T payload, Map<String, Object> headers)
创建一个Message时,会同时生成一个随即的唯一ID。构造器可以接受一个消息头的Map,然后复制其中的消息头到新创建的Message。
还有两个方便的子类可用:StringMessage和ErrorMessage。前者接受一个String作为负载:
StringMessage message = new StringMessage("hello world");
String s = message.getPayload();
后者接受任何Throwable对象作为负载:
ErrorMessage message = new ErrorMessage(someThrowable);
Throwable t = message.getPayload();
注意到这些实现得益于GenericMessage类是参数化的。因此,正如上面的示例,从消息中获取负载对象不需要显示的转换类型。
2.4 MessageBuilderHelper类
你可以注意到Message接口只定义了获取消息负载和消息头的方法,却没有setter。这是因为消息创建后就不能被修改。因此,当一个消息的实例发送给多个消费者(例如通过一个发布订阅通道),如果消费者之一需要使用不同的负载类型发送一个响应,它应该创建一个新的Message。所以,这些变动不会影响其他消费者。记住,多个消费者可以访问同样的消息负载实例和消息头,这样的一个实例是否不可修改取决于开发者。换句话说,Message的契约就像是一个不可修改的集合(unmodifiable Collection),而MessageHeaders的map进一步展示了这一点。虽然MessageHeaders类实现了java.util.Map,但是MessageHeaders上任何一个put(或是remove、clear)操作的调用都会产生一个UnsupportedOperationException异常。
相对于需要创建并填充一个Map然后传递给GenericMessage的构造函数来创建消息,Spring Integration提供了一个更方便的方式:MessageBuilder。MessageBuilder提供了两个工厂方法从一个已经存在的消息或是一个负载对象来构造消息实例。当从一个已经存在的消息构建时,
原有消息的负载和消息头都会被复制到新的消息:
Message<String> message1 = MessageBuilder.withPayload("test")
.setHeader("foo", "bar")
.build();
Message<String> message2 = MessageBuilder.fromMessage(message1).build();
assertEquals("test", message2.getPayload());
assertEquals("bar", message2.getHeaders().get("foo"));
如果需要使用一个新的负载来创建一个消息,但是仍然希望从已经存在的消息复制消息头,你可以使用MessageBuilder的copy方法之一。
Message<String> message3 = MessageBuilder.withPayload("test3")
.copyHeaders(message1.getHeaders())
.build();
Message<String> message4 = MessageBuilder.withPayload("test4")
.setHeader("foo", 123)
.copyHeadersIfAbsent(message1.getHeaders())
.build();
assertEquals("bar", message3.getHeaders().get("foo"));
assertEquals(123, message4.getHeaders().get("foo"));
注意copyHeadersIfAbsent不会覆盖现有的值。在上面的第二个例子中,你也可以看到如何使用setHeader设置用户自定义的消息头。最后,系统提供了一些方法来设置一些预定义的消息头,它们不会妨碍设置任何消息头(MessageHeaders类中也定义了这些预定义消息头名字的常量)。
Message<Integer> importantMessage = MessageBuilder.withPayload(99)
.setPriority(MessagePriority.HIGHEST)
.build();
assertEquals(MessagePriority.HIGHEST, importantMessage.getHeaders().getPriority());
Message<Integer> anotherMessage = MessageBuilder.fromMessage(importantMessage)
.setHeaderIfAbsent(MessageHeaders.PRIORITY, MessagePriority.LOW)
.build();
assertEquals(MessagePriority.HIGHEST, anotherMessage.getHeaders().getPriority());
MessagePrioity是仅仅在使用PrioityChannel时被考虑(将在下一章描述)。它被定义成一个包括5个可能的值的枚举量。
public enum MessagePriority {
HIGHEST,
HIGH,
NORMAL,
LOW,
LOWEST
}
分享到:
相关推荐
基于springboot大学生就业信息管理系统源码数据库文档.zip
基于java的驾校收支管理可视化平台的开题报告
时间序列 原木 间隔5秒钟 20241120
毕业设计&课设_基于 Vue 的电影在线预订与管理系统:后台 Java(SSM)代码,为毕业设计项目.zip
基于springboot课件通中小学教学课件共享平台源码数据库文档.zip
基于java的网上购物商城的开题报告
Delphi人脸检测与识别Demo1fdef-main.zip
基于java的咖啡在线销售系统的开题报告
基于java的自助医疗服务系统的开题报告.docx
内容概要:本文档全面介绍了Visual Basic(VB)编程语言的基础知识和高级应用。首先概述了VB的基本特性和开发环境,随后详细讲述了VB的数据类型、变量、运算符、控制结构、数组、过程与函数、变量作用域等内容。接着介绍了窗体设计、控件使用、菜单与工具栏的设计,文件操作、数据库访问等关键知识点。最后讨论了VB的学习方法、发展历史及其在桌面应用、Web应用、数据库应用、游戏开发和自动化脚本编写等领域的广泛应用前景。 适合人群:初学者和中级程序员,尤其是希望快速掌握Windows桌面应用开发的人群。 使用场景及目标:①掌握VB的基础语法和开发环境;②学会使用VB创建复杂的用户界面和功能完整的应用程序;③理解数据库操作、文件管理和网络编程等高级主题。 其他说明:Visual Basic是一种简单易学且功能强大的编程语言,尤其适合用于开发Windows桌面应用。文中不仅覆盖了基础知识,还包括了大量的实用案例和技术细节,帮助读者快速提升编程技能。
基于java的疫情期间高校防控系统开题报告.docx
基于springboot+vue社区老年人帮扶系统源码数据库文档.zip
基于java的超市商品管理系统的开题报告.docx
基于SpringBoot房屋买卖平台源码数据库文档.zip
xdu限通院23微处理器系统与应用大作业(两只老虎),适应于汇编语言keil软件,
<项目介绍> - 新闻类网站系统,基于SSM(Spring、Spring MVC、MyBatis)+MySQL开发,高分成品毕业设计,附带往届论文 - 不懂运行,下载完可以私聊问,可远程教学 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 --------
基于java的学生网上请假系统的开题报告.docx
社会经济繁荣发展的今天,电子商务得到了飞速发展,网上交易越来越彰显出其独特的优越性,在人们的日常生活中,出现了各种类型的交易网站。其中一个就是车辆易主交易网站,它是一个服务于用户买卖二手车辆的交易网站,为用户提供了平等互利、方便快捷的网上交易平台,通过这一类型的网站,用户可自由出售和购买车辆。 本课题主要根据车辆本身的特性,充分发挥互联网的特点与优势,构建一个以二手车辆为商品、基于互联网平台的车辆易主业务交易管理系统,并根据车辆易主业务交易管理系统的应用需求,进行需求分析,进而对网站系统作规划设计。采用IDEA为运行平台,以SSH为框架,运用HTML语言、JSP技术、MySql数据库、JSP与后台数据库链接等关键技术建设二手车网上交易系统,构建车辆易主交易系统的会员注册与登录,网站首页展示、用户发布商品车辆,用户求购商品车辆,分页浏览、购物系统、用户后台管理、管理员用户后台管理等功能,并使这些功能得以实现并更好为用户服务。网站整体构建完成且测试成功后,用户可以进入网站进行注册、登录,登录后,用户可以在网站上发布自己的闲置车辆或者寻找想要购买的车辆,还可以收藏车辆,管理发布和收藏的车辆,
SQLite3的向量扩展库,windows dll,版本0.1.5
基于C++实现(控制台)商品库存管理系统