消息隊列:快速上手ActiveMQ消息隊列的JMS方式使用(兩種模式:Topic和Queue的消息推送和訂閱)
- 2019 年 11 月 1 日
- 筆記
版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/eguid_1/article/details/79300799
1、實現功能
希望使用一套API,實現兩種模式下的消息發送和接收功能,方便業務程式調用
1、發送Topic
2、發送Queue
3、接收Topic
4、接收Queue
2、介面設計
根據功能設計公共調用介面
/** * 數據分發介面(用於發送、接收消息隊列數據) * * @author eguid * */ public interface MsgDistributeInterface { /** * 發送到主題 * * @param topicName -主題 * @param data -數據 * @return */ public boolean sendTopic(String topicName, byte[] data); /** * 發送到主題 * @param topicName -主題 * @param data-數據 * @param offset -偏移量 * @param length -長度 * @return */ boolean sendTopic(String topicName, byte[] data, int offset, int length); /** * 發送到隊列 * * @param queueName -隊列名稱 * @param data -數據 * @return */ public boolean sendQueue(String queueName, byte[] data); /** * 發送到隊列 * @param queueName -隊列名稱 * @param data -數據 * @param offset * @param length * @return */ public boolean sendQueue(String queueName, byte[] data,int offset, int length); /** * 接收隊列消息 * @param queueName 隊列名稱 * @param listener * @throws JMSException */ void receiveQueue(String queueName, MessageListener listener) throws JMSException; /** * 訂閱主題 * @param topicName -主題名稱 * @param listener * @throws JMSException */ void receiveTopic(String topicName, MessageListener listener) throws JMSException; }3、基於ActiveMQ的介面實現
/** * 基於activeMQ的消息生產者/消費者實現(初始化該對象時即初始化連接消息隊列,如果無法連接到消息隊列,立即拋出異常) * * @author eguid * */ public class ActiveMQImpl implements MsgDistributeInterface { private String userName; private String password; private String brokerURL; private boolean persistentMode;//持久化模式 //連接工廠 ConnectionFactory connectionFactory; //發送消息的執行緒 Connection connection; // 事務管理 Session session; //存放各個執行緒訂閱模式生產者 ThreadLocal<MessageProducer> topicThreadLocal = new ThreadLocal<MessageProducer>(); //存放各個執行緒隊列模式生產者 ThreadLocal<MessageProducer> queueThreadLocal = new ThreadLocal<MessageProducer>(); public ActiveMQImpl(String userName, String password, String brokerURL) throws JMSException { this(userName, password, brokerURL, true); } public ActiveMQImpl(String userName, String password, String brokerURL,boolean persistentMode) throws JMSException { this.userName = userName; this.password = password; this.brokerURL = brokerURL; this.persistentMode=persistentMode; init(); } public void init() throws JMSException { try { // 創建一個鏈接工廠 connectionFactory = new ActiveMQConnectionFactory(this.userName, this.password, this.brokerURL); // 從工廠中創建一個鏈接 connection = connectionFactory.createConnection(); // 開啟鏈接 connection.start(); // 創建一個事務(訂閱模式,事務採用自動確認方式) session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); } catch (JMSException e) { throw e; } } @Override public boolean sendTopic(String topicName, byte[] data) { return sendTopic(topicName, data, 0, data.length); } @Override public boolean sendTopic(String topicName, byte[] data, int offset, int length) { return send(true, topicName, data, offset, length); } @Override public boolean sendQueue(String queueName, byte[] data) { return sendQueue(queueName, data, 0, data.length); } @Override public boolean sendQueue(String queueName, byte[] data, int offset, int length) { return send(false, queueName, data, offset, length); } /** * 發送數據 * * @param name * @param data * @param offset * @param length * @param type * -類型 * @return */ private boolean send(boolean type, String name, byte[] data, int offset, int length) { try { MessageProducer messageProducer = getMessageProducer(name, type); BytesMessage msg = createBytesMsg(data, offset, length); System.err.println(Thread.currentThread().getName()+"發送消息"); // 發送消息 messageProducer.send(msg); } catch (JMSException e) { return false; } return false; } public void receive(String topicName) throws JMSException { final Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); Topic topic =session.createTopic(topicName); MessageConsumer consumer=session.createConsumer(topic); consumer.setMessageListener(new MessageListener() { @Override public void onMessage(Message message) { BytesMessage msg=(BytesMessage) message; System.err.println(Thread.currentThread().getName()+"收到消息:"+msg.toString()); } }); } /** * 創建位元組數組消息 * * @param data * @param offset * @param length * @return * @throws JMSException */ private BytesMessage createBytesMsg(byte[] data, int offset, int length) throws JMSException { BytesMessage msg = session.createBytesMessage(); msg.writeBytes(data, offset, length); return msg; } /** * 創建對象序列化消息 * @param obj * @return * @throws JMSException */ private ObjectMessage createMapMsg(Serializable obj) throws JMSException { // MapMessage msg = session.createMapMessage();//key-value形式的消息 ObjectMessage msg = session.createObjectMessage(obj); return msg; } /** * 創建字元串消息 * @param text * @return * @throws JMSException */ private TextMessage createTextMsg(String text) throws JMSException { TextMessage msg = session.createTextMessage(text); return msg; } /** * 獲取創建者 * * @param name -名稱(主題名稱和隊列名稱) * @param type -類型(true:topic,false:queue) * @return * @throws JMSException */ private MessageProducer getMessageProducer(String name, boolean type) throws JMSException { return type?getTopicProducer(name):getQueueProducer(name); } /** * 創建或獲取隊列 * @param queueName * @return * @throws JMSException */ private MessageProducer getQueueProducer(String queueName) throws JMSException { MessageProducer messageProducer = null; if ((messageProducer = queueThreadLocal.get()) == null) { Queue queue = session.createQueue(queueName); messageProducer = session.createProducer(queue); //是否持久化(1-不持久化(如果沒有消費者,消息就也會自動失效),2-持久化(如果沒有消費者進行消費,消息隊列也會快取消息等待消費者進行消費)) messageProducer.setDeliveryMode(persistentMode?DeliveryMode.PERSISTENT:DeliveryMode.NON_PERSISTENT); queueThreadLocal.set(messageProducer); } return messageProducer; } /** * 創建或獲取主題 * @param topicName * @return * @throws JMSException */ private MessageProducer getTopicProducer(String topicName) throws JMSException { MessageProducer messageProducer = null; if ((messageProducer = topicThreadLocal.get()) == null) { Topic topic = session.createTopic(topicName); messageProducer = session.createProducer(topic); //是否持久化(1-不持久化(如果沒有消費者,消息就也會自動失效),2-持久化(如果沒有消費者進行消費,消息隊列也會快取消息等待消費者進行消費)) messageProducer.setDeliveryMode(persistentMode?DeliveryMode.PERSISTENT:DeliveryMode.NON_PERSISTENT); topicThreadLocal.set(messageProducer); } return messageProducer; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public void receiveQueue(String queueName,MessageListener listener) throws JMSException { final Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); Queue topic =session.createQueue(queueName); MessageConsumer consumer=session.createConsumer(topic); consumer.setMessageListener(listener); } @Override public void receiveTopic(String topicName,MessageListener listener) throws JMSException { final Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); Topic topic =session.createTopic(topicName); MessageConsumer consumer=session.createConsumer(topic); consumer.setMessageListener(listener); }4、測試一下Topic和Queue
public static void main(String[] args) throws JMSException{ //如果創建失敗會立即拋出異常 MsgDistributeInterface producter = new ActiveMQImpl("system", "manager", "tcp://127.0.0.1:61616"); Test testMq = new Test(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Thread 1 new Thread(testMq.new ProductorMq(producter)).start(); //Thread 2 new Thread(testMq.new ProductorMq(producter)).start(); //Thread 3 new Thread(testMq.new ProductorMq(producter)).start(); //Thread 4 new Thread(testMq.new ProductorMq(producter)).start(); //Thread 5 new Thread(testMq.new ProductorMq(producter)).start(); //Thread 6 new Thread(testMq.new ProductorMq(producter)).start(); //訂閱接收執行緒Thread 1 new Thread(new Runnable() { @Override public void run() { try { producter.receiveTopic("eguid-topic",new MessageListener() { @Override public void onMessage(Message message) { BytesMessage msg=(BytesMessage) message; System.err.println(Thread.currentThread().getName()+"訂閱主題消息:"+msg.toString()); } }); } catch (JMSException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); //訂閱接收執行緒Thread 2 new Thread(new Runnable() { @Override public void run() { try { producter.receiveTopic("eguid-topic",new MessageListener() { @Override public void onMessage(Message message) { BytesMessage msg=(BytesMessage) message; System.err.println(Thread.currentThread().getName()+"訂閱主題消息:"+msg.toString()); } }); } catch (JMSException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); //隊列消息生產執行緒Thread-1 new Thread(testMq.new QueueProductor(producter)).start(); //隊列消息生產執行緒Thread-2 new Thread(testMq.new QueueProductor(producter)).start(); //隊列接收執行緒Thread 1 new Thread(new Runnable() { @Override public void run() { try { producter.receiveQueue("eguid-queue",new MessageListener() { @Override public void onMessage(Message message) { BytesMessage msg=(BytesMessage) message; System.err.println(Thread.currentThread().getName()+"收到隊列消息:"+msg.toString()); } }); } catch (JMSException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); //隊列接收執行緒Thread2 new Thread(new Runnable() { @Override public void run() { try { producter.receiveQueue("eguid-queue",new MessageListener() { @Override public void onMessage(Message message) { BytesMessage msg=(BytesMessage) message; System.err.println(Thread.currentThread().getName()+"收到隊列消息:"+msg.toString()); } }); } catch (JMSException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); } private class ProductorMq implements Runnable{ Jtt809MsgProducter producter; public ProductorMq(Jtt809MsgProducter producter){ this.producter = producter; } @Override public void run() { while(true){ try { String wang=Thread.currentThread().getName()+"Hello eguid! This is topic."; producter.sendTopic("eguid-topic",wang.getBytes()); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } private class QueueProductor implements Runnable{ Jtt809MsgProducter producter; public QueueProductor(Jtt809MsgProducter producter){ this.producter = producter; } @Override public void run() { while(true){ try { String eguid=Thread.currentThread().getName()+"Hello eguid! This is queue."; producter.sendQueue("eguid-queue",eguid.getBytes()); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
