1、正常情况下能正常接收
1、创建交换机、队列、绑定交换机和 队列
package com.sky.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 尹稳健~
* @version 1.0
*/
@Configuration
public class ConfirmRabbitMQConfig {
// 声明交换机
@Bean
public DirectExchange confirmExchange(){
return new DirectExchange("confirm_exchange",true,false);
}
// 声明队列
@Bean
public Queue confirmQueue(){
return new Queue("confirm_queue",true);
}
// 绑定交换机和队列
@Bean
public Binding confirmQueueBind(){
return BindingBuilder.bind(confirmQueue()).to(confirmExchange()).with("confirm");
}
}
2、发送消息
public void makeOrderConfirm(String userId, String productId, int num) {
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功"+orderId);
String exchangeName = "confirm_exchange";
String routeKey = "confirm";
rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId+"----success");
}
3、测试
2、交换机发生故障的情况下如何发现消息没有发送过去
1、创建交换机和队列
同上。略。
2、创建配置类
当消息没有被确认时,执行回调方法,这个回调方法需要手动应答
package com.sky.config;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
/**
* @author 尹稳健~
* @version 1.0
* 回调接口
*/
@Configuration
public class MyCallBack implements RabbitTemplate.ConfirmCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
// 因为是RabbitTemplate的内部接口,所以需要注入
@PostConstruct
public void init(){
rabbitTemplate.setConfirmCallback(this);
}
// 交换机确认回调方法
/**
*
* @param correlationData 消息的相关信息
* @param ack 是否确认消息
* @param cause 错误的原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (!ack){
System.out.println("交换机没有收到信息:"+correlationData.getId()+",原因是:"+cause);
System.out.println("接收失败!");
}else{
System.out.println("接收成功!");
}
}
}
3、编写yml配置
server:
port: 8080
spring:
# RabbitMQ配置
rabbitmq:
host: localhost
port: 5672
username: admin
password: admin
virtual-host: /
# 确认消息回调方法
publisher-confirm-type: correlated
4、发送消息故意将交换机名称写错
public void makeOrderConfirm(String userId, String productId, int num) {
String orderId = UUID.randomUUID().toString();
CorrelationData correlationData = new CorrelationData();
correlationData.setId("1");
System.out.println("订单生成成功"+orderId);
String exchangeName = "confirm_exchange";
String routeKey = "confirm";
rabbitTemplate.convertAndSend(exchangeName+"1",routeKey,orderId+"----success",correlationData);
rabbitTemplate.convertAndSend(exchangeName,routeKey+"1",orderId+"-----false",correlationData);
}
5、测试
报错,交换机不存在,接受失败
3、交换机能接受到消息,但是队列无法接受到消息,那么怎么让消息回退到交换机中去呢?
1、创建交换机、队列、绑定交换机
同上、略。
2、编写配置类
因为RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback是RabbitTemplate中的内部接口,所以调用之前需要注入。
package com.sky.config;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
/**
* @author 尹稳健~
* @version 1.0
* 回调接口
*/
@Configuration
public class MyCallBack implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
// 因为是RabbitTemplate的内部接口,所以需要注入
@PostConstruct
public void init(){
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setReturnsCallback(this);
}
// 交换机确认回调方法
/**
*
* @param correlationData 消息的相关信息
* @param ack 是否确认消息
* @param cause 错误的原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (!ack){
System.out.println("交换机没有收到信息:"+correlationData.getId()+",原因是:"+cause);
System.out.println("接收失败!");
}else{
System.out.println("接收成功!");
}
}
// 消息回退
// 只有不可到达目的地的时候才会回退
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
System.out.println(returnedMessage.getMessage()+
"消息发送失败,退回交换机"+returnedMessage.getExchange());
}
}
3、编写yml配置
server:
port: 8080
spring:
# RabbitMQ配置
rabbitmq:
host: localhost
port: 5672
username: admin
password: admin
virtual-host: /
# 确认消息回调方法
publisher-confirm-type: correlated
# 退回消息
publisher-returns: true
4、发送消息,故意将队列名称写错
public void makeOrderConfirm(String userId, String productId, int num) {
String orderId = UUID.randomUUID().toString();
CorrelationData correlationData = new CorrelationData();
correlationData.setId("1");
System.out.println("订单生成成功"+orderId);
String exchangeName = "confirm_exchange";
String routeKey = "confirm";
rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId+"----success",correlationData);
rabbitTemplate.convertAndSend(exchangeName,routeKey+"1",orderId+"-----false",correlationData);
}
5、测试
注意这里消息发送失败了,退回到交换机中了。
下面的接收成功是交换机接收成功,不是队列!
4、备份交换机
备份交换机,用来备份交换机发送队列的失败消息。
备份交换机中有2各队列:一个是备份消息的队列还有一个是预警队列
// 这里因为是要备份所以使用这种方式创建
return ExchangeBuilder.directExchange(“confirm_exchange”)
.withArgument(“alternate-exchange”,“backup_exchange”).build();
1、创建交换机和队列 绑定
package com.sky.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 尹稳健~
* @version 1.0
*/
// 备份交换机 和 备份队列 报警队列
@Configuration
public class BackRabbitMQConfig {
// 声明交换机
@Bean
public FanoutExchange backupExchange(){
return new FanoutExchange("backup_exchange");
}
// 声明队列
@Bean
public Queue backupQueue(){
return new Queue("backup_queue",true);
}
@Bean
public Queue warningQueue(){
return new Queue("warning_queue",true);
}
// 绑定交换机和队列
@Bean
public Binding backupBinding(){
return BindingBuilder.bind(backupQueue()).to(backupExchange());
}
@Bean
public Binding warningBinding(){
return BindingBuilder.bind(warningQueue()).to(backupExchange());
}
}
package com.sky.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 尹稳健~
* @version 1.0
*/
@Configuration
public class ConfirmRabbitMQConfig {
// 声明交换机
@Bean
public DirectExchange confirmExchange(){
// 这里因为是要备份所以使用这种方式创建
return ExchangeBuilder.directExchange("confirm_exchange")
.withArgument("alternate-exchange","backup_exchange").build();
}
// 声明队列
@Bean
public Queue confirmQueue(){
return new Queue("confirm_queue",true);
}
// 绑定交换机和队列
@Bean
public Binding confirmQueueBind(){
return BindingBuilder.bind(confirmQueue()).to(confirmExchange()).with("confirm");
}
}
2、发送消息(一条正确的和一条错误的)
public void makeOrderConfirm(String userId, String productId, int num) {
String orderId = UUID.randomUUID().toString();
CorrelationData correlationData = new CorrelationData();
correlationData.setId("1");
System.out.println("订单生成成功"+orderId);
String exchangeName = "confirm_exchange";
String routeKey = "confirm";
rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId+"----success",correlationData);
rabbitTemplate.convertAndSend(exchangeName,routeKey+"1",orderId+"-----false",correlationData);
}
3、测试
接收后:
返回报警队列中的消息,和一条发送正确的消息