<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.10.0</version>
</dependency>
</dependencies>
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmListener;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class SendMessage {
private final static String QUEUE_NAME = "test";
private final static String ROUTE_KEY = QUEUE_NAME;
private final static String MESSAGE = "I love three things in this world,the sun ,the moon and you.";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
{
factory.setHost("49.232.202.201");
factory.setUsername("gosuncn");
factory.setPassword("123456");
factory.setVirtualHost("/gosuncn");
}
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
/**
* 消息确认模式[confirm]
*/
channel.confirmSelect();
/**
* 添加确认监听器
*/
channel.addConfirmListener(new ConfirmListener() {
//只要是交换机确认收到了消息就会回调ConfirmListener的handleAck方法。(即使交换机没有正确路由到队列中)
@Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
if (multiple) {
System.out.println("Before No." + deliveryTag + " have been confirmed.");
} else {
System.out.println("No." + deliveryTag + " have been confirmed.");
}
}
//只要是交换机没有确认收到了消息就会回调ConfirmListener的handleNack方法。
@Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
if (multiple) {
System.out.println("Before No." + deliveryTag + " have been not confirmed.");
} else {
System.out.println("No." + deliveryTag + " have been not confirmed.");
}
}
});
/**
* 如果消息到达了交换机且路由不可达那么回调ReturnListener的方法。
* void basicPublish(String exchange, String routingKey, boolean mandatory, BasicProperties props, byte[] body)
* 生效条件:第三个参数 mandatory 需要设置为true。
*/
channel.addReturnListener((replyCode, replyText, exchange, routingKey, properties, body) -> {
System.out.println(replyCode);
System.out.println(replyText);
System.out.println(exchange);
System.out.println(routingKey);
});
/**
* 发布消息
*/
channel.basicPublish("", ROUTE_KEY, true, null, MESSAGE.getBytes());
System.out.println("message delivery [" + MESSAGE + "]");
}
}
第1步:开启confirm模式
channel.confirmSelect();
第2步:添加确认回调
void addConfirmListener(ConfirmListener listener);
public interface ConfirmListener {
void handleAck(long deliveryTag, boolean multiple) throws IOException;
void handleNack(long deliveryTag, boolean multiple) throws IOException;
}
需要重写两个方法handleAck和handleNack。
这样,已经可以实现Confirm的回调了。那么到底是什么时机执行回调呢?
handleAck方法:消息被basicPublish到RabbitMQ的交换机上,一旦确认收到消息,就会回调。
handleNack方法:与之相反,没有确认收到消息,就会回调。
如果消息被送达交换机,但是交换机没有正确的路由到队列中,该怎么办呢?
只有队列可以存储消息,交换机并不能,如果交换机没有正确的路由到队列中,消息可能丢失。
这时,我们需要使用Return监听器,来回调非正确路由的业务逻辑。
void addReturnListener(ReturnListener listener);
但是,要想Return监听器生效,需要将
void basicPublish(String exchange, String routingKey, boolean mandatory, BasicProperties props, byte[] body)中
第三个参数 mandatory 设置为true,才行。
本文介绍了RabbitMQ的消息确认(Confirm)和返回(Return)机制。通过开启Confirm模式并设置确认回调,当消息成功到达交换机时会触发handleAck方法,未成功则触发handleNack。若消息无法正确路由到队列,需配合监听器和参数设置为true来处理非正确路由的情况,确保消息不会丢失。
5185

被折叠的 条评论
为什么被折叠?



