上一篇我們已經知道消費者確認消息了,但是如果每個queue都要定義自己的確認信息的話,不免有點累贅,那我們就在一個地方設置一下全局確認信息即可,所以這一篇只告訴你怎麼設置全局,其他代碼請查看上一篇內容
package com.lwl.rabbitmq;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.lwl.rabbitmq.constant.Constants;
/**
*
* 設置全局確認信息
*
* @author lwl
* @create 2019年6月17日 下午1:34:45
* @version 1.0
*/
@SpringBootApplication
public class RabbitmqAckApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitmqAckApplication.class, args);
}
/**
* 自動確認涉及到一個問題就是如果在處理消息的時候拋出異常,消息處理失敗,但是因爲自動確認而導致 Rabbit 將該消息刪除了,造成消息丟失
* @param connectionFactory
* @return
* @author lwl
* @create 2019年6月17日 上午11:13:14
*/
// @Bean
// public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
// SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
// container.setConnectionFactory(connectionFactory);
// container.setQueueNames(Constants.TOPIC_QUEUE); // 監聽的隊列
// container.setAcknowledgeMode(AcknowledgeMode.NONE); // NONE 代表自動確認
// container.setMessageListener((MessageListener) message -> { //消息監聽處理
// System.out.println();
// System.out.println();
// System.out.println("====接收到消息=====");
// System.out.println(new String(message.getBody()));
// System.out.println();
// System.out.println();
// //相當於自己的一些消費邏輯拋錯誤
// throw new NullPointerException("consumer fail");
// });
// return container;
// }
/**
* AcknowledgeMode 除了 NONE 和 MANUAL 之外還有 AUTO ,它會根據方法的執行情況來決定是否確認還是拒絕(是否重新入queue)
如果消息成功被消費(成功的意思是在消費的過程中沒有拋出異常),則自動確認
當拋出 AmqpRejectAndDontRequeueException 異常的時候,則消息會被拒絕,且 requeue = false(不重新入隊列)
當拋出 ImmediateAcknowledgeAmqpException 異常,則消費者會被確認
其他的異常,則消息會被拒絕,且 requeue = true(如果此時只有一個消費者監聽該隊列,則有發生死循環的風險,多消費端也會造成資源的極大浪費,這個在開發過程中一定要避免的)。可以通過 setDefaultRequeueRejected(默認是true)去設置
*/
/**
* 手動確認消息
* @param connectionFactory
* @return
* @author lwl
* @create 2019年6月17日 下午1:01:43
*/
@Bean
public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(Constants.TOPIC_QUEUE); // 監聽的隊列
container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // 手動確認
container.setMessageListener((ChannelAwareMessageListener) (message, channel) -> { //消息處理
System.out.println("====接收到消息=====");
System.out.println(new String(message.getBody()));
if(message.getMessageProperties().getHeaders().get("error") == null){
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
System.out.println("消息已經確認");
}else {
//channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
System.out.println("消息拒絕");
}
});
return container;
}
/**
* AUTO 根據情況確定
* @param connectionFactory
* @return
* @author lwl
* @create 2019年6月17日 下午1:14:44
*/
// @Bean
// public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
// SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
// container.setConnectionFactory(connectionFactory);
// container.setQueueNames("consumer_queue"); // 監聽的隊列
// container.setAcknowledgeMode(AcknowledgeMode.AUTO); // 根據情況確認消息
// container.setMessageListener((MessageListener) (message) -> {
// System.out.println("====接收到消息=====");
// System.out.println(new String(message.getBody()));
// //拋出NullPointerException異常則重新入隊列
// //throw new NullPointerException("消息消費失敗");
// //當拋出的異常是AmqpRejectAndDontRequeueException異常的時候,則消息會被拒絕,且requeue=false
// //throw new AmqpRejectAndDontRequeueException("消息消費失敗");
// //當拋出ImmediateAcknowledgeAmqpException異常,則消費者會被確認
// throw new ImmediateAcknowledgeAmqpException("消息消費失敗");
// });
// return container;
// }
}
其他代碼請參考上一篇內容,測試也參考上一篇。