连接工具类:
public enum ConnUtil {
INSTANCE;
public Connection getConn() throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("admin");
factory.setPassword("admin");
factory.setVirtualHost("/test_host");
factory.setHost("localhost");
factory.setPort(5672);
return factory.newConnection();
}
}
生产者:
public class RProducer {
public static void main(String[] args) throws Exception {
Connection conn = ConnUtil.INSTANCE.getConn();
Channel channel = conn.createChannel();
channel.queueDeclare("reconsumer_queue", false, false, false, null);
String msg = "hello world ";
//总共发送5条消息
for (int i = 1; i < 6; i++) {
//为每条消息设置一个id
BasicProperties properties = new BasicProperties.Builder().messageId(String.valueOf(i)).build();
channel.basicPublish("", "reconsumer_queue", properties, (msg + i).getBytes());
System.out.println("send msg:" + (msg + i));
}
}
}
消费者:
public class RConsumer {
public static void main(String[] args) throws Exception {
Connection conn = ConnUtil.INSTANCE.getConn();
Channel channel = conn.createChannel();
channel.queueDeclare("reconsumer_queue", false, false, false, null);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
System.out.println("receiver msg:" + new String(body, "UTF-8"));
long deliveryTag = envelope.getDeliveryTag();
//消息id为1的消息进行重新消费
if ("1".equals(properties.getMessageId())) {
channel.basicNack(deliveryTag, false, true);
return;
}
channel.basicAck(deliveryTag, false);
}
};
channel.basicConsume("reconsumer_queue", false, consumer);
}
}
控制台输出:
receiver msg:hello world 1
receiver msg:hello world 2
receiver msg:hello world 3
receiver msg:hello world 4
receiver msg:hello world 5
receiver msg:hello world 1
receiver msg:hello world 1
receiver msg:hello world 1
receiver msg:hello world 1
receiver msg:hello world 1
receiver msg:hello world 1
... ...
消息messageid为1的消息会无限重复消费下去。看下控制台:
确实有一条未消费的消息在队列中。看一下:
确实是第一条消息。现在我们吧demo改一下:
public class RConsumer {
public static volatile int reConsumerCount = 0;
public static void main(String[] args) throws Exception {
Connection conn = ConnUtil.INSTANCE.getConn();
Channel channel = conn.createChannel();
channel.queueDeclare("reconsumer_queue", false, false, false, null);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
System.out.println("receiver msg:" + new String(body, "UTF-8"));
long deliveryTag = envelope.getDeliveryTag();
if ("1".equals(properties.getMessageId())) {
if (reConsumerCount < 5) {
channel.basicNack(deliveryTag, false, true);
reConsumerCount++;
return;
}
}
channel.basicAck(deliveryTag, false);
}
};
channel.basicConsume("reconsumer_queue", false, consumer);
}
}
控制台输出:
receiver msg:hello world 1
receiver msg:hello world 1
receiver msg:hello world 1
receiver msg:hello world 1
receiver msg:hello world 1
receiver msg:hello world 1
六次后消费成功,为什么是六次呢, 五次不成功的加上一次成功的。
看下控制台:
确实消费成功了。