rabbitmq 整个消息投递的路径为:
producer--->rabbitmq broker--->exchange--->queue--->consumer
消息从 producer 到 exchange 则会返回一个 confirmCallback 。
消息从 exchange-->queue 投递失败则会返回一个 returnCallback 。
我们将利用这两个 callback 控制消息的可靠性投递
1 修改application.yml文件
server:
port: 8021
spring:
#给项目来个名字
application:
name: rabbitmq-test
#配置rabbitMq 服务器
rabbitmq:
host: 127.0.0.1
port: 5672
username: need
password: 123456
#虚拟host 可以不设置,使用server默认host
virtual-host: /testhost
#确认消息已发送到交换机(Exchange) 可以把publisher-confirms: true 替换为 publisher-confirm-type: correlated
publisher-confirm-type: correlated
#确认消息已发送到队列(Queue)
publisher-returns: true
2 编写配置类 RabbitConfig
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
@Bean
public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate();
rabbitTemplate.setConnectionFactory(connectionFactory);
//设置消息投递失败的策略,有两种策略:自动删除或返回到客户端。
//我们既然要做可靠性,当然是设置为返回到客户端(true是返回客户端,false是自动删除)
rabbitTemplate.setMandatory(true);
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println();
System.out.println("相关数据:" + correlationData);
if (ack) {
System.out.println("投递成功,确认情况:" + ack);
} else {
System.out.println("投递失败,确认情况:" + ack);
System.out.println("原因:" + cause);
}
}
});
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println();
System.out.println("ReturnCallback: " + "消息:" + message);
System.out.println("ReturnCallback: " + "回应码:" + replyCode);
System.out.println("ReturnCallback: " + "回应信息:" + replyText);
System.out.println("ReturnCallback: " + "交换机:" + exchange);
System.out.println("ReturnCallback: " + "路由键:" + routingKey);
System.out.println();
}
});
return rabbitTemplate;
}
}
3 生产者代码测试
import cn.huawei.rabbitmqtest1.pojo.User;
import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.UUID;
@SpringBootTest
class RabbitmqTest1ApplicationTests_1 {
@Autowired
RabbitTemplate rabbitTemplate; //使用RabbitTemplate,这提供了接收/发送等等方法
@Test
public void test_3() {
for (int i = 1; i <= 5; i++) {
//这个参数是用来做消息的唯一标识
//发布消息时使用,存储在消息的headers中
CorrelationData correlationData = new CorrelationData(i+"");
User user = new User(i + "", "陈四 " + i);
if (i == 2) {
//故意把交换机写错,演示 confirmCallback
rabbitTemplate.convertAndSend("TestDirectExchange_111", "TestDirectRouting", JSON.toJSONString(user), correlationData);
} else if (i == 3) {
//故意把路由键写错,演示 returnCallback
rabbitTemplate.convertAndSend("TestDirectExchange", "TestDirectRouting_111", JSON.toJSONString(user), correlationData);
} else {
//正常发送
rabbitTemplate.convertAndSend("TestDirectExchange", "TestDirectRouting", JSON.toJSONString(user), correlationData);
}
}
}
}