RabbitMQ发送消息的工具类
代码如下:
java
@Component
public class Sender {
@Autowired
private AmqpTemplate rabbitTemplate;
public void send(String routingKey, String message) {
this.rabbitTemplate.convertAndSend(routingKey, message);
}
public void send(String exchange, String routingKey, String message) {
this.rabbitTemplate.convertAndSend(exchange, routingKey, message);
}
}
send() 方法封装了 RabbitMQ 的消息发送机制,通过 AmqpTemplate(具体来说是 rabbitTemplate)来发送消息。下面我们详细分析这两个 send() 方法的实现逻辑及其影响:
1. send(String routingKey, String message)
java
public void send(String routingKey, String message) {
this.rabbitTemplate.convertAndSend(routingKey, message);
}
实现细节 :这个方法调用了 rabbitTemplate.convertAndSend(routingKey, message) ,其中:
routingKey :消息发送时使用的路由键。
message:要发送的实际消息内容。
默认行为:如果只指定了路由键而没有指定交换器,RabbitMQ 会默认使用默认交换器(Default Exchange)。默认交换器是一个直连交换器(Direct Exchange),它根据完全匹配的队列名作为路由键,将消息路由到对应的队列中。
适用场景:
这种方法适用于简单路由,当只需要通过一个路由键来决定消息应该发送到哪个队列时使用。如果路由键与队列名完全相同,RabbitMQ 会将消息直接发送到对应的队列。
eg:
当调用 mqSenderUtil.send("QUEUE_HI", "hi1 message") 时,消息将通过默认交换器,根据 QUEUE_HI 这个路由键被路由到名称为 QUEUE_HI 的队列。
2. send(String exchange, String routingKey, String message)
java
public void send(String exchange, String routingKey, String message) {
this.rabbitTemplate.convertAndSend(exchange, routingKey, message);
}
实现细节 :这个方法提供了发送消息时指定交换器的功能。它调用了 rabbitTemplate.convertAndSend(exchange, routingKey, message),其中:
exchange :消息应该通过哪个交换器发送。
routingKey :消息在该交换器中的路由键。
message:要发送的消息内容。
自定义行为:在这种情况下,开发者可以明确指定消息要通过哪个交换器发送,并且可以结合交换器的类型(如主题交换器、直连交换器、扇出交换器等)和路由键进行灵活的消息路由。
适用场景:
这种方法适用于复杂的路由需求,比如需要发送消息到特定的交换器,或者需要使用不同的路由规则来匹配多个队列。开发者可以根据需要指定不同的交换器和路由键,从而实现更复杂的消息路由机制。
eg :
当调用 mqSenderUtil.send("Exchange@topic.welcome", "hello.b", "hello2 message") 时,消息会被发送到指定的主题交换器 Exchange@topic.welcome,并使用 hello.b 作为路由键。交换器会根据它的路由规则,将消息发送到匹配 hello.b 的队列。
两个方法的区别:
方法一:只使用路由键,消息会通过默认交换器发送,路由规则相对简单,适用于单个队列的消息发送。
方法二:指定了交换器和路由键,消息可以通过不同类型的交换器发送,允许更灵活的消息路由,适用于需要复杂路由的场景。
下面我们再来看一下在Controller中是怎么用的
java
public class HelloController {
@Autowired
private MQSenderUtil mqSenderUtil;
@ApiOperation("发送到指定hi队列")
@PostMapping("hi")
public void hi() {
mqSenderUtil.send(RabbitMQConstant.QUEUE_HI, "hi1 message:" + LocalDateTime.now());
}
@ApiOperation("发送到指定路由")
@PostMapping("hello1")
public void hello1() {
mqSenderUtil.send("hello.a", "hello1 message:" + LocalDateTime.now());
}
@ApiOperation("发送到指定交换器和路由")
@PostMapping("hello2")
public void hello2() {
mqSenderUtil.send("Exchange@topic.welcome","hello.b", "hello2 message:" + LocalDateTime.now());
}
}
hi() 方法:
java
mqSenderUtil.send(RabbitMQConstant.QUEUE_HI, "hi1 message:" + LocalDateTime.now());
调用第一个 send() 方法,将消息发送到名为 QUEUE_HI 的队列,依赖于 RabbitMQ 的默认交换器,消息会通过完全匹配的路由键直接路由到这个队列。
hello1() 方法:
java
mqSenderUtil.send("hello.a", "hello1 message:" + LocalDateTime.now());
同样调用第一个 send() 方法,消息会通过默认交换器,使用 hello.a 作为路由键进行路由。具体的行为取决于是否有队列与该路由键绑定。
hello2() 方法:
java
mqSenderUtil.send("Exchange@topic.welcome", "hello.b", "hello2 message:" + LocalDateTime.now());
调用第二个 send() 方法,明确指定了要发送到的交换器 Exchange@topic.welcome,并使用路由键 hello.b。这个消息将会通过主题交换器并根据路由键的匹配规则被路由到相应的队列。
总结:
hi() 和 hello1() 方法 使用第一个 send(),通过默认交换器发送消息,直接使用路由键进行简单路由。
hello2() 方法 使用第二个 send(),通过自定义交换器和路由键发送消息,支持更加灵活的消息路由。
由此我们可以知道,
当我的路由键是hello.*(带通配符,非精准匹配)那么只能调用第二个send方法。因为默认交换器不支持使用通配符。
调用第一个 send 方法:
java
public void send(String routingKey, String message) {
this.rabbitTemplate.convertAndSend(routingKey, message);
}
当您调用这个方法并传入 hello.* 作为路由键时,RabbitMQ 会尝试将消息发送到默认交换器(直连交换器)。由于默认交换器仅支持完全匹配的路由键(即路由键必须与队列名称完全相同),因此这会导致消息无法被成功路由到任何队列。
调用第二个 send 方法:
java
public void send(String exchange, String routingKey, String message) {
this.rabbitTemplate.convertAndSend(exchange, routingKey, message);
}
使用这个方法时,您可以指定一个主题交换器(例如,Exchange@topic.welcome)作为参数,并将 hello.* 作为路由键传递。主题交换器允许使用通配符进行路由,因此,RabbitMQ 将会根据绑定规则和通配符逻辑将消息路由到匹配的队列。
这也就是send()方法重载的意义所在。