Cofirm消息确认
理解Cofirm消息确认的流程解析
- 在channel上开启确认模式:channel.confirmSelect()
- 在channel上添加监听,addConfirmListener,监听成功和失败的返回结果,根据具体的结果对消息进行重新发送,或记录日志等后续处理!
代码如下:
package com.example.rabbitmq.confirm;
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 producer {
public static void main(String[] args) throws IOException, TimeoutException {
//1,创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//2, 获取连接
Connection connection = connectionFactory.newConnection();
//3, 通过connection创建一个channel
Channel channel = connection.createChannel();
//4, 指定投递模式, 消息的确认模式
channel.confirmSelect();
String exchangeName = "test_confirm_exchange";
String routingKey = "confirm_save";
//5, 发送消息
String msg = "hello rabbitmq send confirm message!";
channel.basicPublish(exchangeName, routingKey, null, msg.getBytes());
//6, 添加一个确认监听
channel.addConfirmListener(new ConfirmListener() {
@Override
public void handleAck(long l, boolean b) throws IOException {
System.out.println("----- ack -----");
}
@Override
public void handleNack(long l, boolean b) throws IOException {
System.out.println("----- not ack -----");
}
});
//channel.close();
//connection.close();
}
}
消费者代码:
package com.example.rabbitmq.confirm;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 消费者
*/
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//1,创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//2,获取连接
Connection connection = connectionFactory.newConnection();
//3,通过connection创建一个channel
Channel channel = connection.createChannel();
//4,exchange, routingkey, queue, 并将queue和交换机绑定
//设置交换机
String exchangeName = "test_confirm_exchange";
String routingKey = "confirm_save";
String queueName = "test_confirm_queue";
//声明一个交换机
channel.exchangeDeclare(exchangeName, "topic", true);
//声明一个队列
channel.queueDeclare(queueName, true, false, false, null);
//建立关系
channel.queueBind(queueName, exchangeName, routingKey);
//5,创建消费者//
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//6,设置channel
channel.basicConsume(queueName, true, queueingConsumer);
//7,获取消息
while (true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("msg = " + msg);
}
}
}
Return 消息机制
return listener 用于处理一些不可路由的消息
我们的消费生产者,通过指定的exchange和routingkey,把消息送达到一个队列中, 然后消费者监听队列,处理消息
在特定的情况下,我们发送消息的时候,当前的exchange不存在或者指定的routingkey路由不到,这个时候需要监听这种不可达的消息,就要使用Return Listener.
关键配置项:
Mandatory:如果为true,则监听器会接收到路由不可达的消息,然后进行后续处理,如果为false,那么broker会自动删除消息。默认为false;
生产者代码:
package com.example.rabbitmq.returnlistener;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 生产者
*/
public class producer {
public static void main(String[] args) throws IOException, TimeoutException {
//1,创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//2, 获取连接
Connection connection = connectionFactory.newConnection();
//3, 通过connection创建一个channel
Channel channel = connection.createChannel();
String exchangeName = "test_return_exchange";
String routingKey = "return.save";
String routingKeyError = "abc.save";
//5, 发送消息
String msg = "hello rabbitmq send retuen message!";
channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int replyCode, String replyText, String exchange, String routingKey,
AMQP.BasicProperties basicProperties, byte[] bytes) throws IOException {
System.out.println("----- handle return -----");
System.out.println("replyCode = " + replyCode);
System.out.println("replyText = " + replyText);
System.out.println("exchange = " + exchange);
System.out.println("properties = " + basicProperties);
System.out.println("msg = " + new String(bytes));
}
});
channel.basicPublish(exchangeName, routingKeyError, true,null, msg.getBytes());
// channel.close();
// connection.close();
}
}
消费者代码:
package com.example.rabbitmq.returnlistener;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 消费者
*/
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//1,创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
//2,获取连接
Connection connection = connectionFactory.newConnection();
//3,通过connection创建一个channel
Channel channel = connection.createChannel();
//4,exchange, routingkey, queue, 并将queue和交换机绑定
//设置交换机
String exchangeName = "test_return_exchange";
String routingKey = "return.#";
String queueName = "test_return_queue";
//声明一个交换机
channel.exchangeDeclare(exchangeName, "topic", true);
//声明一个队列
channel.queueDeclare(queueName, true, false, false, null);
//建立关系
channel.queueBind(queueName, exchangeName, routingKey);
//5,创建消费者//
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//6,
channel.basicConsume(queueName, true, queueingConsumer);
//7,获取消息
while (true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("msg = " + msg);
}
}
}