Return Listener用於處理一些不可路由的消息!
我們的消息生產者,通過指定一個ExChange和Routingkey,把消息送達到某一個隊列種去,然後我們的消費者監聽隊列,進行消費處理操作!
但是在某些情況下,如果我們在發送消息的時候,當前的Exchange不存在或者指定的路由key路由不到,這個時候如果我們需要監聽種不可達的消息,就要使用Return Listener!
在基礎的API種有一個關鍵的配置項:Mandatory:如果爲true,則監聽器會接受到路由不可達的消息,然後進行後續處理,如果爲false,那麼broker端自動刪除該消息!
消費者代碼
package com.star.movie.returnlistener;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
import com.star.movie.common.Constant;
import com.rabbitmq.client.QueueingConsumer.Delivery;
/**
* @Description:消費者
* @author:kaili
* @Date: 2019-04-22 17:41
**/
public class ReturnConsumer {
public static void main(String[] args) throws Exception{
Connection connection = Constant.getConnection();
Channel channel = connection.createChannel();
String exchangeName = "test_return_exchange";
String routingKey = "return.#";
String queueName = "test_return_queue";
channel.exchangeDeclare(exchangeName, "topic", true, false, null);
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey);
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, queueingConsumer);
while(true){
Delivery delivery = queueingConsumer.nextDelivery();
String msg = new String(delivery.getBody());
System.err.println("消費者: " + msg);
}
}
}
生產者代碼快
package com.star.movie.returnlistener;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ReturnListener;
import com.star.movie.common.Constant;
import java.io.IOException;
/**
* @Description:生產者
* @author:kaili
* @Date: 2019-04-22 17:41
**/
public class ReturnProducer {
public static void main(String[] args) throws Exception{
Connection connection = Constant.getConnection();
Channel channel = connection.createChannel();
String exchange = "test_return_exchange";
String routingKey = "return.save";
String routingKeyError = "abc.save";
String msg = "Hello RabbitMQ Return Message";
channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int replyCode, String replyText, String exchange, String routingKey,
AMQP.BasicProperties properties, byte[] body) throws IOException {
System.err.println("---------handle return----------");
System.err.println("replyCode: " + replyCode);
System.err.println("replyText: " + replyText);
System.err.println("exchange: " + exchange);
System.err.println("routingKey: " + routingKey);
System.err.println("properties: " + properties);
System.err.println("body: " + new String(body));
}
});
//發送送達不到的消息mandatory屬性爲true
// channel.basicPublish(exchange, routingKeyError, false, null, msg.getBytes());
//發送送達不到的消息mandatory屬性爲false
channel.basicPublish(exchange, routingKeyError, true, null, msg.getBytes());
//發送正常消息
// channel.basicPublish(exchange, routingKey, true, null, msg.getBytes());
}
}
step 1 啓動消費者代碼
生成test_return_exchange交換機,綁定test_return_queue隊列,綁定健爲return.#,類型爲topic
step 2 啓動消費者代碼
使用發送送達不到的消息mandatory屬性爲false這種發送方式,觀察控制檯打印消息。
消息發送失敗,沒有路由到對應的隊列,在return監聽代碼中打印了相關消息路由的消息。
step 3 修改消費者代碼再次啓動
使用發送送達不到的消息mandatory屬性爲true這種發送方式,觀察控制檯打印消息。
生產者控制檯沒有任何消息
觀察消費者控制檯
消費者控制檯也沒有任何消息,說明該消息未發送到Broker,return監聽也未接收到任何消息。這是因爲Mandatory屬性設置開啓和關閉不同下的不同處理結果。