RabbitMQ基础篇之Java客户端 基于注解声明队列交换机
文章目录
- 1. 基于 Java Bean 声明队列、交换机和绑定关系
- 2. 案例:使用 Java 代码声明 Direct Exchange
- 3. 基于注解声明队列、交换机及绑定关系(优化方案)
- 4. 注解方式的优缺点对比
- 5. 总结与选择
- 6. 实践演示
1. 基于 Java Bean 声明队列、交换机和绑定关系
使用 Java Bean 方式声明队列、交换机及其绑定关系。这样做的好处是,项目启动时 Spring AMQP 会自动根据代码创建队列、交换机,并建立绑定关系。代码简洁且自动化,适合大部分简单的配置需求。
问题: 使用 Java Bean 方式时,如果需要绑定多个 routing key,需要重复写绑定代码,导致配置类变得冗长,维护起来比较麻烦。
2. 案例:使用 Java 代码声明 Direct Exchange
在实际的项目中,我们需要删除现有的队列和交换机,然后重新用 Java 代码声明。以下是 Direct Exchange 声明的关键步骤:
- 声明交换机(Exchange)
@Bean
public FanoutExchange directExchange() {
//return ExchangeBuilder.fanoutExchange("nhuan.direct").build(); // 方式一
return new FanoutExchange("nhuan.direct"); // 方式二
}
- 声明队列(Queue)
@Bean
public Queue directQueue1() {
//return QueueBuilder.durable("direct.queue1").build(); // 方式一
return new Queue("direct.queue1"); // 方式二
}
@Bean
public Queue directQueue2() {
//return QueueBuilder.durable("direct.queue2").build();
return new Queue("direct.queue2");
}
- 队列与交换机的绑定(Binding)
@Bean
public Binding fanoutQueue1BindingRed(Queue directQueue1, DirectExchange directExchange) {
return BindingBuilder.bind(directQueue1).to(directExchange).with("red");
}
@Bean
public Binding fanoutQueue1BindingBlue(Queue directQueue1, DirectExchange directExchange) {
return BindingBuilder.bind(directQueue1).to(directExchange).with("blue");
}
@Bean
public Binding fanoutQueue2BindingRed(Queue fanoutQueue2, DirectExchange directExchange) {
return BindingBuilder.bind(fanoutQueue2).to(directExchange).with("red");
}
@Bean
public Binding fanoutQueue2BindingYellow(Queue fanoutQueue2, DirectExchange directExchange) {
return BindingBuilder.bind(fanoutQueue2).to(directExchange).with("yellow");
}
- 完整示例
package com.itheima.consumer.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DirectConfiguration {
@Bean
public FanoutExchange directExchange() {
//return ExchangeBuilder.fanoutExchange("nhuan.direct").build(); // 方式一
return new FanoutExchange("nhuan.direct"); // 方式二
}
@Bean
public Queue directQueue1() {
//return QueueBuilder.durable("direct.queue1").build(); // 方式一
return new Queue("direct.queue1"); // 方式二
}
@Bean
public Binding fanoutQueue1BindingRed(Queue directQueue1, DirectExchange directExchange) {
return BindingBuilder.bind(directQueue1).to(directExchange).with("red");
}
@Bean
public Binding fanoutQueue1BindingBlue(Queue directQueue1, DirectExchange directExchange) {
return BindingBuilder.bind(directQueue1).to(directExchange).with("blue");
}
@Bean
public Queue directQueue2() {
//return QueueBuilder.durable("direct.queue2").build();
return new Queue("direct.queue2");
}
@Bean
public Binding fanoutQueue2BindingRed(Queue fanoutQueue2, DirectExchange directExchange) {
return BindingBuilder.bind(fanoutQueue2).to(directExchange).with("red");
}
@Bean
public Binding fanoutQueue2BindingYellow(Queue fanoutQueue2, DirectExchange directExchange) {
return BindingBuilder.bind(fanoutQueue2).to(directExchange).with("yellow");
}
}
问题:
- 每增加一个绑定关系,就需要额外声明一个
**Binding**
。 - 对于多个绑定键(如
**red**
,**blue**
),需要重复创建绑定代码,导致类非常冗长。
3. 基于注解声明队列、交换机及绑定关系(优化方案)
为了简化上述问题,Spring AMQP 提供了一种基于注解的方式来声明队列、交换机和绑定关系。这样可以减少代码冗余,并且支持更多灵活的配置。注解在消息监听器中使用。
关键注解:
@RabbitListener
- 用于声明消费者并指定队列。@QueueBinding
- 用于声明队列与交换机的绑定关系。@Queue
- 用于声明队列。@Exchange
- 用于声明交换机。@Binding
- 用于指定绑定关系和 routing key。
示例:
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "direct.queue1", durable = "true"),
exchange = @Exchange(name = "nhuan.direct", type = ExchangeTypes.DIRECT),
key = {"red", "blue"}
))
public void listenDirectQueue1(String message) {
log.info("消费者1接收到 direct.queue1 的消息: " + message);
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "direct.queue2", durable = "true"),
exchange = @Exchange(name = "nhuan.direct", type = ExchangeTypes.DIRECT),
key = {"red", "yellow"}
))
public void listenDirectQueue2(String message) {
log.info("消费者2接收到 direct.queue2 的消息: " + message);
}
解释:
@RabbitListener
用来声明消费者。@QueueBinding
用来声明队列与交换机的绑定关系,绑定关系中指定了交换机名称、类型(如direct
)和多个 binding key。@Queue
用来声明队列的名称。@Exchange
用来声明交换机的名称和类型。
优势:
- 简化代码:不再需要为每个 binding key 创建多个
Binding
实例。 - 支持多个绑定键:可以在
key
属性中传递一个数组,绑定多个 routing key。 - 更简洁:通过注解一次性声明队列、交换机及绑定关系。
4. 注解方式的优缺点对比
特性 | 基于 Java Bean 声明 | 基于注解声明 |
---|---|---|
配置简洁性 | 配置类较为冗长,需要为每个绑定声明多个 Binding 实例。 | 配置简洁,多个绑定键通过数组一次性完成。 |
代码维护性 | 随着绑定键的增加,代码复杂度增大。 | 注解方式更直观,易于维护。 |
灵活性 | 灵活,可通过 Java 代码灵活配置队列和交换机。 | 灵活性较低,但对于简单场景更为适用。 |
自动创建 | 自动创建队列和交换机,减少手动操作。 | 同样可以自动创建队列和交换机。 |
5. 总结与选择
-
基于 Java Bean 声明:适合复杂的配置场景,需要灵活控制交换机、队列和绑定的参数。
-
基于注解声明:适合简单的绑定配置,代码更加简洁和易维护,特别是在绑定键数量较少时。
开发中选择使用哪种方式: -
可以根据项目需求和个人喜好选择使用 Java Bean 或注解方式。注解方式在简单场景下非常方便,但在复杂场景下,Java Bean 方式提供了更多的控制和灵活性。
6. 实践演示
启动项目后,自动创建了交换机、队列及绑定关系,并成功处理了消息。