为什么需要Return
Return Listener用于处理一些不可路由的消息
生产者通过指定Exchange和RoutingKey将消息发送达指定队列,消费者只需监听这个队列,进行消费操作。
但是在某些情况下,我们在发送消息的时候,当前Exchange不存在或者指定的路由key路由不到,这个时候我们如果需要监听这种达不到的消息,我们就需要使用Return Listener。
实现
流程图:
在API中配置项:
Mandatory
:如果为true
,则会监听路由不可达消息,然后进行后续处理;如果为false
,那么broker自动删除这条消息。
代码实现
Producer
package com.wyg.rabbitmq.javaclient.producer_return;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.*;
/**
* 生产端return机制
*
* @author wyg0405@gmail.com
* @date 2019-11-22 13:25
* @since JDK1.8
* @version V1.0
*/
public class Producer {
private static final String HOST = "localhost";
private static final int PORT = 5672;
private static final String USERNAME = "guset";
private static final String PASSWORD = "guset";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(HOST);
factory.setVirtualHost("/");
factory.setPort(PORT);
factory.setUsername(USERNAME);
factory.setPassword(PASSWORD);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
String exchangeName = "test_return_exchange";
String routingKey = "return.ok";
String routingKeyError = "return.error";
// 申明exchange
channel.exchangeDeclare(exchangeName, "topic");
// 添加监听
channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int replyCode, String replyText, String exchange, String routingKey,
AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("---生产端---");
System.out.println("replyCode:" + replyCode);
System.out.println("replyText:" + replyText);
System.out.println("exchange:" + exchange);
System.out.println("routingKey:" + routingKey);
System.out.println("properties:" + properties);
System.out.println("body:" + new String(body));
}
});
// 设置 mandatory 为 true
boolean mandatory = true;
String msg = "这是一条return确认消息1,routingKey " + routingKey;
channel.basicPublish(exchangeName, routingKey, mandatory, null, msg.getBytes("UTF-8"));
String msg2 = "这是一条return确认消息2,routingKey " + routingKeyError;
channel.basicPublish(exchangeName, routingKeyError, mandatory, null, msg2.getBytes("UTF-8"));
}
// 注意,因为要等待broker的return消息,暂时不关闭channel和connection
}
Conusumer
package com.wyg.rabbitmq.javaclient.producer_return;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.*;
/**
* 生产端return机制
*
* @author wyg0405@gmail.com
* @date 2019-11-22 14:07
* @since JDK1.8
* @version V1.0
*/
public class Consumer {
private static final String HOST = "localhost";
private static final int PORT = 5672;
private static final String USERNAME = "guset";
private static final String PASSWORD = "guset";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(HOST);
factory.setVirtualHost("/");
factory.setPort(PORT);
factory.setUsername(USERNAME);
factory.setPassword(PASSWORD);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
String queueName = "test_return_queue";
String exchangeName = "test_return_exchange";
String routingKey = "return.ok";
// 申明exchange
channel.exchangeDeclare(exchangeName, "topic");
// 申明队列
channel.queueDeclare(queueName, true, false, false, null);
// 队列绑定到exchange
channel.queueBind(queueName, exchangeName, routingKey, null);
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
try {
System.out.println("---消费者---:" + new String(message.getBody(), "UTF-8"));
} finally {
// consumer手动 ack 给broker
channel.basicAck(message.getEnvelope().getDeliveryTag(), false);
}
}
};
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
System.out.println("---消费者:cancelCallback");
}
};
// 消费消息
channel.basicConsume(queueName, false, deliverCallback, cancelCallback);
}
}
注意
先运行Consumer,绑定正确的exchange和routingKey,再启动生产者
运行结果
Consumer
Producer,其中routingKey 为 return.error的消息无法路由,被Return Listener监听到
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。