在我们的rabbit队列配置类里设置RabbitTemplate
举例:
package com.gmtgo.demo.topic;
import com.gmtgo.demo.config.RabbitConfirmCallback;
import com.gmtgo.demo.config.RabbitConfirmReturnCallBack;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
/**
* @author 大帅
*/
@Configuration
public class TopicQueueConfig {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostConstruct
public void initRabbitTemplate() {
// 设置生产者消息确认
rabbitTemplate.setConfirmCallback(new RabbitConfirmCallback());
rabbitTemplate.setReturnCallback(new RabbitConfirmReturnCallBack());
}
/**
* 声明队列名.
*/
private final String topic1 = "topic_queue_1";
private final String topic2 = "topic_queue_2";
/**
* 声明交换机的名字.
*/
private final String topicExchange = "topicExchange";
/**
* 声明队列.
*
* @return
*/
@Bean
public Queue topicQueue1() {
return new Queue(topic1);
}
@Bean
public Queue topicQueue2() {
return new Queue(topic2);
}
/**
* 声明路由交换机.
*
* @return
*/
@Bean
public TopicExchange topicExchange() {
return new TopicExchange(topicExchange);
}
/**
* 队列绑定交换机,指定routingKey,也可在可视化工具中进行绑定.
*
* @return
*/
@Bean
Binding bindingTopicExchange1(Queue topicQueue1, TopicExchange exchange) {
return BindingBuilder.bind(topicQueue1).to(exchange).with("topic.keyA");
}
/**
* 队列绑定交换机,指定routingKey,也可在可视化工具中进行绑定.
* 绑定的routing key 也可以使用通配符:
* *:匹配不多不少一个词
* #:匹配一个或多个词
*
* @return
*/
@Bean
Binding bindingTopicExchange2(Queue topicQueue2, TopicExchange exchange) {
return BindingBuilder.bind(topicQueue2).to(exchange).with("topic.#");
}
}
启动项目发送消息,消息被正常消费,confim回调返回ack=true如果我们将exchange修改,发送到一个不存在的exchange中,会怎么样呢?
会发现confirm回调为false,打印出结果为不存在topicExchange1111的交换机
如果我们在消费端处理逻辑时出错会怎么样呢?修改消费端代码我们在消费时让它报错
confirm回调为true,但是在rabbitmq的web界面会发现存在5条没有消费的消息
如果我们把
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
中最后一个参数改为false呢,会发现在web管理界面没有未被消费的消息,说明这条消息已经被摒弃。
实际开发中,到底是打回到队列呢还是摒弃,要看自己的需求,但是打回队列应该有次数限制,不然会陷入死循环。
继续测试,将routingKey修改为一个没有的key,
7.5 结论
如果消息没有到exchange,则confirm回调,ack=false
如果消息到达exchange,则confirm回调,ack=true
exchange到queue成功,则不回调return
exchange到queue失败,则回调return
8. 项目示例代码:
下载地址:springboot-rabbitmq-demo_1619322789961