AMQP 抽象
Spring AMQP 由两个模块组成(每个模块在发行版中用一个 JAR 表示):春季-AMQP和春兔.
“spring-amqp”模块包含org.springframework.amqp.core包。
在该包中,你可以找到代表核心AMQP“模型”的类。
我们的目标是提供通用抽象,不依赖于任何特定的AMQP代理实现或客户端库。
终端用户代码在不同厂商实现间更具可移植性,因为它可以仅针对抽象层开发。
这些抽象随后通过经纪人专用模块实现,如“Spring兔”。
目前只有RabbitMQ实现。
然而,这些抽象已在 .NET 中通过 Apache Qpid 和 RabbitMQ 验证。
由于AMQP在协议层面运行,原则上你可以将RabbitMQ客户端与任何支持相同协议版本的代理商使用,但目前我们不测试其他代理。
本概述假设您已熟悉AMQP规范的基础知识。 如果没有,可以看看“其他资源”中列出的资源
消息
0-9-1 AMQP规范并未定义消息职业或界面。
相反,当执行如下作时,basicPublish(),内容作为字节数组参数传递,其他属性作为独立参数传递。
Spring AMQP 定义了消息类作为更通用的AMQP域模型表示的一部分。
目的消息类旨在将主体和属性封装在单一实例中,从而使API更简单。
以下示例展示了消息类别定义:
public class Message {
private final MessageProperties messageProperties;
private final byte[] body;
public Message(byte[] body, MessageProperties messageProperties) {
this.body = body;
this.messageProperties = messageProperties;
}
public byte[] getBody() {
return this.body;
}
public MessageProperties getMessageProperties() {
return this.messageProperties;
}
}
这消息属性界面定义了若干常见属性,如“messageId”、“timestamp”、“contentType”等。
你也可以通过调用setHeader(字符串键,对象值)方法。
从版本开始1.5.7,1.6.11,1.7.4和2.0.0,如果消息体是序列化的序列 化Java 对象,执行时默认不再反序列化toString()作(例如日志消息中)。
这是为了防止不安全的反串列。
默认情况下,只有java.util和java.lang类被解序列化。
要恢复到之前的行为,可以通过调用 添加允许的类/包模式Message.addAllowedListPatterns(...).
例如,支持一个简单的万用符*com.something.*, *.我的课堂.
无法反序列化的主体由 表示为字节[<大小>]在日志消息中。 |
交换
这交换接口代表AMQP交换,即消息生产者发送的交换。
经纪商虚拟主机内的每个交易所都有独特的名称以及其他一些属性。
以下示例展示了交换接口:
public interface Exchange extends Declarable {
String getName();
String getType();
boolean isDurable();
boolean isAutoDelete();
Map<String, Object> getArguments();
}
如你所见,一个交换也有一个“类型”,由定义在 的常量表示。交换类型.
基本类型包括:直接,主题,扇形和头.
在核心包中,你可以找到以下实现交换每种类型的接口。
行为在这些平台之间有所不同交换类型是它们处理队列绑定的方式。
例如,一个直接Exchange 允许队列被固定路由密钥(通常是队列名称)绑定。
一个主题Exchange 支持带有路由模式的绑定,这些模式可能包含分别代表“正好一”和“零或更多”的“*”和“#”万用符。
这扇形Exchange会向所有绑定到它的队列发布,而不考虑任何路由密钥。
有关这些及其他交易所类型的更多信息,请参见AMQP交易所。
从3.2版本开始,一致性哈希交换为了在应用配置阶段的便利性,引入了类型。
它提供了以下选项x-一致哈希对于交换类型来说。
允许配置哈希头或哈希属性交换定义论证。
相应的RabbitMQrabbitmq_consistent_hash_exchange插件必须在经纪人中启用。
关于一致性哈希交换的目的、逻辑和行为的更多信息,请参阅官方 RabbitMQ 文档。
AMQP规范还要求任何经纪商提供一个“默认”的直接交换,且没有名称。
所有声明的队列都绑定在该默认状态下交换他们的名字作为路由密钥。
你可以在 Spring AMQP 中了解更多关于默认 Exchange 的使用情况Amqp模板. |
队列
这队列类代表消息消费者接收消息的组件。
就像各种交换我们的实现旨在抽象地表示该核心AMQP类型。
以下列表显示了队列类:
public class Queue {
private final String name;
private final boolean durable;
private final boolean exclusive;
private final boolean autoDelete;
/**
* The queue is durable, non-exclusive and non auto-delete.
*
* @param name the name of the queue.
*/
public Queue(String name) {
this(name, true, false, false);
}
// Getters and Setters omitted for brevity
}
注意构造程序采用队列名称。 根据实现不同,管理员模板可能提供生成唯一命名队列的方法。 此类队列可作为“回复”地址或其他临时情况使用。 因此,自动生成队列的“exclusive”和“autoDelete”属性都会被设置为“true”。
| 关于如何通过命名空间支持声明队列的信息,请参见“配置代理”中的队列部分,包括队列参数。 |
捆绑
鉴于生产者向交换发送信息,消费者从队列接收,连接队列与交换机构的绑定对于通过消息连接生产者和消费者至关重要。
在春季AMQP中,我们定义了一个捆绑用类来表示这些连接。
本节回顾了将队列绑定到交换的基本选项。
我们提供装订构建器以促进“流畅 API”风格,如下示例所示:
Queue queue = ...;
// bind a queue to a DirectExchange with a fixed routing key
Binding directBinding = BindingBuilder.bind(queue).to(new DirectExchange("someDirectExchange")).with("foo.bar");
// bind a queue to a TopicExchange with a routing pattern
Binding topicBinding = BindingBuilder.bind(queue).to(new TopicExchange("someTopicExchange")).with("foo.*");
// bind a queue to a FanoutExchange with no routing key
Binding fanoutBinding = BindingBuilder.bind(queue).to(new FanoutExchange("someFanoutExchange"));
为清晰起见,前面的例子展示了装订构建器但这种风格在使用静态导入“bind()”方法时效果很好。 |
单独而言,是捆绑类只保存关于连接的数据。
换句话说,它不是一个“主动”组件。
然而,正如你将在后续的“配置经纪人”中看到的,AmqpAdmin类可以使用捆绑实例以触发经纪人对其的约束性作。
此外,正如你在同一节中看到的,你可以定义捆绑通过使用 Spring 的实例@Bean注释@Configuration类。
还有一个方便的基类,进一步简化了生成AMQP相关豆定义的方法,并识别队列、交换和绑定,使它们在应用启动时全部声明在AMQP代理上。
这Amqp模板也定义在核心包中。
作为实际AMQP消息传递的主要组成部分之一,它在单独章节中有详细讨论(参见Amqp模板).