一、springboo使用RabbitMQ
二、几种常见模型的简介与使用
1、简单模型(Simple Model)
最基本的消息传递模型,包括一个生产者发送消息到一个队列,然后一个消费者从队列中接收并处理消息。
生产者
@RequiredArgsConstructor
@RestController
@RequestMapping("publisher")
public class PublisherController {
private final RabbitTemplate rabbitTemplate;
@GetMapping()
public String sendMess(String queueName ,String message ){
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 22);
rabbitTemplate.convertAndSend("simple.queue",map);
return "发送成功";
}
}
消费者
@RabbitListener(queues = "simple.queue")
public void listener6 (Map<String, Object> map){
System.out.println("消费者1接收到了消息:"+map);
}
结果
2、发布/订阅模型(Publish/Subscribe Model)
消息被发送到一个交换机(Exchange),然后交换机将消息广播给绑定到它的所有队列,每个队列都有一个消费者来处理消息。
生产者
public String sendMess(String queueName ,String message ){
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 22);
rabbitTemplate.convertAndSend("test","",map);
return "发送成功";
}
消费者
/**
* ExchangeTypes.FANOUT 广播,将消息交给所有绑定到交换机的队列
* @param mess
*/
@RabbitListener(bindings = @QueueBinding(value = @Queue, exchange = @Exchange(value = "test", type = ExchangeTypes.FANOUT)))
public void listener2(Map<String, Object> mess){
System.out.println("消费者3接收到了消息:"+mess);
}
/**
* ExchangeTypes.FANOUT 广播,将消息交给所有绑定到交换机的队列
* @param mess
*/
@RabbitListener(bindings = @QueueBinding(value = @Queue, exchange = @Exchange(value = "test", type = ExchangeTypes.FANOUT)))
public void listener3(Map<String, Object> mess){
System.out.println("消费者4接收到了消息:"+mess);
}
结果
3、工作队列模型(Work Queue Model)
一个生产者发送消息到一个队列,多个消费者从队列中接收并处理消息,消息会被平均分配给消费者。
生产者
public String sendMess(String queueName ,String message ){
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 22);
rabbitTemplate.convertAndSend("test","",map);
return "发送成功";
}
消费者
@RabbitListener(queues = "simple.queue")
public void listener6 (Map<String, Object> map){
System.out.println("消费者6接收到了消息:"+map);
}
@RabbitListener(queues = "simple.queue")
public void listener7 (Map<String, Object> map){
System.out.println("消费者7接收到了消息:"+map);
}
@RabbitListener(queues = "simple.queue")
public void listener8 (Map<String, Object> map){
System.out.println("消费者8接收到了消息:"+map);
}
@RabbitListener(queues = "simple.queue")
public void listener9 (Map<String, Object> map){
System.out.println("消费者9接收到了消息:"+map);
}
结果
4、路由模型(Routing Model)
消息通过路由键(Routing Key)和绑定键(Binding Key)进行路由,生产者将消息发送到交换机,交换机根据绑定键将消息路由到匹配的队列中。
(1)生产者发送的routingKey消费者同时都有,则都打印信息
生产者
public String sendMess(String queueName ,String message ){
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 22);
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("amq.direct","red",map);
}
return "发送成功";
}
消费者
@RabbitListener(bindings = @QueueBinding(value = @Queue,key = {
"blue", "red"}, exchange = @Exchange(value = "amq.direct", type = ExchangeTypes.DIRECT)))
public void listener (Map<String, Object> mess){
System.out.println("消费者1接收到了消息:"+mess);
}
@RabbitListener(bindings = @QueueBinding(value = @Queue,key = {
"black", "red"}, exchange = @Exchange(value = "amq.direct", type = ExchangeTypes.DIRECT)))
public void listener10 (Map<String, Object> mess){
System.out.println("消费者10接收到了消息:"+mess);
}
结果
(1)生产者发送的routingKey某个消费者拥有,则有的那个消费者打印信息
生产者
public String sendMess(String queueName ,String message ){
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 22);
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("amq.direct","blue",map);
}
return "发送成功";
}
消费者
@RabbitListener(bindings = @QueueBinding(value = @Queue,key = {
"blue", "red"}, exchange = @Exchange(value = "amq.direct", type = ExchangeTypes.DIRECT)))
public void listener (Map<String, Object> mess){
System.out.println("消费者1接收到了消息:"+mess);
}
@RabbitListener(bindings = @QueueBinding(value = @Queue,key = {
"black", "red"}, exchange = @Exchange(value = "amq.direct", type = ExchangeTypes.DIRECT)))
public void listener10 (Map<String, Object> mess){
System.out.println("消费者10接收到了消息:"+mess);
}
结果
5、主题模型(Topic Model)
消息通过主题(Topic)进行路由,生产者将消息发送到交换机,交换机根据主题将消息路由到匹配的队列中,主题可以使用通配符进行匹配。
# 通配符
* (star) can substitute for exactly one word. 匹配不多不少恰好1个词
# (hash) can substitute for zero or more words. 匹配一个或多个词
test.* 只能匹配 test.irs
test.# 可匹配test.irs.corporate 或者 test.irs 等
public String sendMess(String queueName ,String message ){
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 22);
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("amq.topic","test.irs.test",map);
}
return "发送成功";
}
消费者
/**
* ExchangeTypes.TOPIC key = "china.#" 通配符,把消息交给符合routing pattern(路由模式) 的队列, #:匹配一个或多个词 , *:匹配不多不少恰好1个词
* @param mess
*/
@RabbitListener(bindings = @QueueBinding(value = @Queue, exchange = @Exchange(value = "amq.topic", type = ExchangeTypes.TOPIC), key = {
"test.*"}))
public void listener1(Map<String, Object> mess){
System.out.println("消费者2接收到了消息:"+mess);
}
@RabbitListener(bindings = @QueueBinding(value = @Queue, exchange = @Exchange(value = "amq.topic", type = ExchangeTypes.TOPIC), key = {
"test.#"} ))
public void listener5(Map<String, Object> mess){
System.out.println("消费者5接收到了消息:"+mess);
}
结果:因为生产者发送的routingKey为test.irs.test,而消费者5为test.#,消费者2为test.*,则消费者5接收到消息
总结:这些模型可以根据实际需求进行组合和扩展,以满足复杂的消息传递场景。每种模型都有不同的特点和适用场景,选择合适的模型可以提高消息传递的效率和可靠性。在使用RabbitMQ时,根据具体需求选择适合的模型,合理设计交换机、队列和绑定关系,能够更好地利用RabbitMQ的消息传递功能。