本文是自己的学习笔记,主要参考资料如下
- Spring Integration官方文档:https://docs.spring.io/spring-integration/docs/current/reference/html/index-single.html#message
1、Message的基本结构
消息体的接口定义如下
public interface Message<T> {
T getPayload();
MessageHeaders getHeaders();
}
这是Message的基本接口,下面开始讲解其中的MessageHeaders
。
1.1 MessageHeader的结构
其中的MessageHeaders
类其实是一个Map,它的代码如下所示
public final class MessageHeaders implements Map<String, Object>, Serializable {
...
}
所以该类提供了和Map一样的检索数据的方法,像boolean containKey(Object key);Object get(Object key);
等方法,具体的可以查阅官方文档:
1.1.1、MessageHeaders中重要的成员变量
MessageHeaders中有一些比较重要的成员变量,如下所示
Header Name | Header Type | Usage |
---|---|---|
MessageHeaders.ID | java.util.UUID | 唯一标识一个MessageHeaders实例,实例创建时自动产生,当实例中有数据变化时该属性值会自动变化。 |
MessageHeaders.TIMESTAMP | java.lang.Long | 标识一个MessageHeaders实例的创建时间,也是自动产生,实例中数据变化时该属性值会自动变成修改时间。 |
MessageHeaders.REPLY_CHANNEL | String or MessageChannel | 如果该Message不知道应该发给谁(Channel),也就是对应的OutputChannel 没有配置或者there is no ROUTING_SLIP or the ROUTING_SLIP is exhausted。那么该属性的值就是要指明该Message应该被发给哪个Channel。如果该属性的类型是String ,那表示Channel的bean name。如果该属性的类型是MessageChannel ,那表示由ChannelRegistry 生成的一个Chanenl。 |
MessageHeaders.ERROR_CHANNEL | String or MessageChannel | 和MessageHeaders.REPLY_CHANNEL基本一样,只是该属性表示的是发生错误时Message会被发送到哪个Channel。 |
1.1.2、MessageHeaders使用的注意事项
需要注意的是,尽管MessageHeaders
的本质是一个Map,一旦MessageHeaders
实例初始化之后,任何对这个实例的put, remove, clear都是不允许的,这个map是一个只读类型的Map。所以一个Message中的Header数据只有在初始化时可以指定,之后就不可修改。同时,如果一个Message实例初始化时Header为空,那之后也是不允许只是set之类的操作。
Header之所以要设置成只读类型是因为同一个Message是有可能会被分发给多个Channel,为了保持一致性就不允许再中途修改数据(无论是Payload还是Header)。如果真的有修改的需求那就只能重新创建一个Message。幸运的是,官方给我么提供了一个跟方便的类MessageBuilder
来做这件事,这将在后面的章节中介绍。
这些修改数据的方法要么不提供,要么调用时会发生异常。
1.2、Message的常用实现类
最简单的实现类是GenericMessage
,里面提供了下面两个初始化方法
new GenericMessage<T>(T payload);
new GenericMessage<T>(T payload, Map<String, Object> headers)
同时官方也提供了基础的用来表示错误信息的ErrorMessage
,它可使用异常作为参数创建Message
ErrorMessage message = new ErrorMessage(someThrowable);
Throwable t = message.getPayload();
1.3、MessageBuilder
基于1.1.2
中提到的原因,一个Message在创建以后不能再修改Payload和Header。如果真的有修改的需求那就只能重新创建一个Message。幸运的是,官方给我么提供了一个跟方便的类MessageBuilder
来做这件事。
MessageBuilder
提供了两个工厂方法,可以用Message或者Payload做参数创建实例,如下所示
Message<String> message1 = MessageBuilder.withPayload("test")
.setHeader("foo", "bar")
.build();
Message<String> message2 = MessageBuilder.fromMessage(message1).build();
MessageBuilder
的Header和Payload都是可以随时改变的,具体可看API文档。最终通过build方法构建新的Message。