public class RabbitMQConfirmConsumer {
public static void main(String[] args) throws Exception {
// 1.创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
// 2.根据connectionFactory获取Connection
Connection connection = connectionFactory.newConnection();
// 3.通过Connection创建一个Channel
Channel channel = connection.createChannel();
// 4.声明一个交换机, 队列以及队列的绑定.
String exchangeName = "test_confirm_exchange";
String queueName = "confirm_queue";
String routingKey = "confirm.save";
channel.queueDeclare(queueName, true, false, false, null);
channel.exchangeDeclare(exchangeName, "topic", true);
channel.queueBind(queueName, exchangeName, routingKey);
// 5.创建消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 6.设置channel
channel.basicConsume(queueName, true, consumer);
while (true) {
// 7.获取信息
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String body = new String(delivery.getBody());
System.out.println("消费端: " + body);
}
}
}
public class RabbitMQConfirmProduct {
public static void main(String[] args) throws Exception {
// 1.创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
// 2.根据connectionFactory获取Connection
Connection connection = connectionFactory.newConnection();
// 3.通过Connection创建一个Channel
Channel channel = connection.createChannel();
// 4.指定消息投递模式: 消息确认模式
channel.confirmSelect();
// 4.通过channel发生数据
String message = "Hello world!, RabbitMQ!";
String exchangeName = "test_confirm_exchange";
String routingKey = "confirm.save";
IntStream.range(0, 5).forEach(item -> { try {
channel.basicPublish(exchangeName, routingKey, null, message.getBytes());
} catch (IOException e) { e.printStackTrace();
} });
// 5.监听Broker的返回值
channel.addConfirmListener(new ConfirmListener() {
/**
* 正确返回
* @param deliveryTag: message的唯一ID.
* @param multiple: 是否批量.
* @throws IOException
*/
@Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
}
/**
* 错误返回
* @param deliveryTag: message的唯一ID.
* @param multiple: 是否批量.
* @throws IOException
*/
@Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
}
});
// 6.不能关闭连接, 因为addConfirmListener时异步的不会阻塞程序执行.
// channel.close();
// connection.close();
}
}
public class ReturnListenerProduct {
public static void main(String[] args) throws Exception {
// 1.创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
// 2.根据connectionFactory获取Connection
Connection connection = connectionFactory.newConnection();
// 3.通过Connection创建一个Channel
Channel channel = connection.createChannel();
// 4.通过channel发送数据
String message = "Hello world!, RabbitMQ!";
String exchangeName = "test_return_exchange";
String routingKey = "return.save";
String routingErrorKey = "abc.save";
IntStream.range(0, 5).forEach(item -> {
try {
// 第三个参数即为Mandatory, 为true的时候, 会调用addReturnListener事件.
channel.basicPublish(exchangeName, routingKey, true, null, message.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
});
// 5.监听Broker的返回值
channel.addReturnListener((replyCode, replyText, exchange, routingKey1, properties, body) -> { System.out.println("Return handle");
// 可以把返回的这些数据, 输出日志, 获取传输到监控台, 能够及时发现错误.
});
// 6.不能关闭连接, 因为addConfirmListener时异步的不会阻塞程序执行.
// channel.close();
// connection.close();
}}
public class ReturnListenerConsumer {
public static void main(String[] args) throws Exception {
// 1.创建ConnectionFactory
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
// 2.根据connectionFactory获取Connection
Connection connection = connectionFactory.newConnection();
// 3.通过Connection创建一个Channel
Channel channel = connection.createChannel();
// 4.声明交换机、队列, 以及绑定队列.
String exchangeName = "test_return_exchange";
String routingKey = "return.save";
String queueName = "test001";
channel.exchangeDeclare(exchangeName, "topic", true);
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey, null);
// 5.创建消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 6.设置channel
channel.basicConsume(queueName, true, consumer);
while (true) { // 7.获取信息
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String body = new String(delivery.getBody());
System.out.println("消费端: " + body);
} }
}
DefaultConsumer
类即可。// 设置channel, 自定义消费者监听
channel.basicConsume(queueName, true, new DefaultConsumer(channel) {
/**
* 监听返回.
* @param consumerTag: rabbitMQ生成的一串标记.
* @param envelope: 包含(消息的唯一ID, Exchange_Name, Queue_Name)
* @param properties: 信息头.
* @param body: 信息体.
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException { super.handleDelivery(consumerTag, envelope, properties, body);
}});
void BasicQos(unit prefetchSize, ushort prefetchCount, bool global)
;BasicQos
参数详解:只有在不自动ACK的时候, 才起效。
// 处理限流第一步
channel.basicQos(0, 1, false);
// 处理限流第二步: 设置autoAck设置为false.
channel.basicConsume(queueName, false, new DefaultConsumer(channel) {
/**
* 监听返回.
* @param consumerTag: rabbitMQ生成的一串标记.
* @param envelope: 包含(消息的唯一ID, Exchange_Name, Queue_Name)
* @param properties: 信息头.
* @param body: 信息体.
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException { super.handleDelivery(consumerTag, envelope, properties, body);
// 处理限流第三步: 手动设置ACK;
channel.basicAck(envelope.getDeliveryTag(), false);
}});
消费端的手工ACK和NACK
channel.basicAck(envelope.getDeliveryTag(), false);
手工ACK,确认这条消息收到啦。消费端的重回队列
案列:
channel.basicConsume(queueName, false, new DefaultConsumer(channel) {
/**
* 监听返回.
* @param consumerTag: rabbitMQ生成的一串标记.
* @param envelope: 包含(消息的唯一ID, Exchange_Name, Queue_Name)
* @param properties: 信息头.
* @param body: 信息体.
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException { super.handleDelivery(consumerTag, envelope, properties, body);
/**
* NACK和重回队列
* 1. 使用的是{@link Channel#basicNack(long deliveryTag, boolean multiple, boolean requeue)} api.
* 2. 这个api第三个参数 requeue表示是否重回队列.
*/
channel.basicNack(envelope.getDeliveryTag(), false, false);
//手动设置ACK;
channel.basicAck(envelope.getDeliveryTag(), false);
}});
// 4.正常的声明交换机、队列, 以及绑定队列.
String exchangeName = "test_dlx_exchange";
String routingKey = "dlx.save";
String queueName = "test001";
channel.exchangeDeclare(exchangeName, "topic", true);
// 5.给正常Queue设置, 私信的Exchange. 必须给queueDeclare的arguments设置私信队列配置.
String DLXExchange = "dlx.exchange";
Map<String, Object> arguments = new HashMap<>(1);
arguments.put("x-dead-letter-exchange", DLXExchange); // 这个key是固定的, 不允许被修改.
channel.queueDeclare(queueName, true, false, false, arguments);
channel.queueBind(queueName, exchangeName, routingKey, null);
// 6. 声明私信Exchange和Queue.
channel.exchangeDeclare(DLXExchange, "topic", true);
channel.queueDeclare("DLX_queue", true, false, false, null);
// '#'代表任何的死信, 只要路由到了这个Exchange的时候, 都会被路由到这个queue中.
channel.queueBind("DLX_queue", DLXExchange, "#");