ActiveMQ入門練習

  ActiveMQ 是Apache出品,最流行的,能力強勁的開源消息總線。ActiveMQ 是一個完全支持JMS1.1和J2EE 1.4規範的 JMS Provider實現,儘管JMS規範出臺已經是很久的事情了,但是JMS在當今的J2EE應用中間仍然扮演着特殊的地位。

  JMS即Java消息服務(Java Message Service)應用程序接口,是一個Java平臺中關於面向消息中間件(MOM)的API,用於在兩個應用程序之間,或分佈式系統中發送消息,進行異步通信。Java消息服務是一個與具體平臺無關的API,絕大多數MOM提供商都對JMS提供支持。

  JMS是一種與廠商無關的 API,用來訪問消息收發系統消息,它類似於JDBC(Java Database Connectivity)。這裏,JDBC 是可以用來訪問許多不同關係數據庫的 API,而 JMS 則提供同樣與廠商無關的訪問方法,以訪問消息收發服務。許多廠商都支持 JMS,包括 IBM 的 MQSeries、BEA的 Weblogic JMS service和 Progress 的 SonicMQ。 JMS 使您能夠通過消息收發服務(有時稱爲消息中介程序或路由器)從一個 JMS 客戶機向另一個 JMS客戶機發送消息。
  本篇我將和大家一起分享一下Apache JMS的使用,ApacheMQ:http://activemq.apache.org/,下載後解壓,這裏需要說明,使用之前請先配置Java環境變量。啓動後打開瀏覽器輸入:http://localhost:8161/admin,這裏需要通過密碼登錄,默認用戶名:admin 密碼:admin(用戶名密碼是在conf/users.properties中配置的)
  這樣我們的環境就配置好了。更詳細的解說:http://blog.csdn.net/clj198606061111/article/details/38145597
  下面就是我們如何進行消息的發送和接收,這裏有兩種方式:點對點收發;發佈訂閱。下面我們就一一進行探討。
  首先搭建一下測試環境,這裏我通過Maven進行項目的創建,我們需要引入activemq的核心activemq-all-5.15.2.jar,以及單元測試
  <dependencies>
      <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-all</artifactId>
      <version>${active-mq-version}</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
  </dependencies>

  下面我們就開始消息的收發,先來探討一下點對點的消息收發:

  1、消息的發送

  原理上我們通過ConnectionFactory會話工廠 ---> 創建一個會話連接 ---> 通過會話連接創建一個會話線程 ---> 通過會話線程創建一個消息隊列 ---> 通過會話線程和消息隊列創建一個消息生產者(MessageProducer) ---> 最後由消息生產者進行消息的發送。

private static ConnectionFactory factory;//會話連接工廠
private static Connection connection;//會話連接
private static Session session;//會話接收或發送消息線程
private static Destination destination;//消息隊列
private static MessageProducer messageProducer;//消息發送者

  通過ActiveMQConnectionFactory創建會話工廠

factory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKER_URL);//創建會話連接工廠

  設置會話連接額度地址和用戶名密碼在(這裏我使用的是默認的地址和用戶名密碼)

private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
private static final String BROKER_URL = ActiveMQConnection.DEFAULT_BROKER_URL;

  下面封裝了一下上面的過程:

    /**
     * @Description 發送消息
     * @param queryName 消息隊列名稱
     * @param msg 消息內容
     * @return
     *
     * @author 高尚
     * @version 1.0
     * @date 創建時間:2018年1月31日 下午3:54:22
     */
    public static boolean producerSendQueryMessage(final String queryName, final String msg){
        boolean flag = true;
        try {
            connection = factory.createConnection();//創建會話連接
            connection.start();//啓動會話連接
            session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);//創建會話線程
            destination = session.createQueue(queryName);//創建消息隊列
            messageProducer = session.createProducer(destination);//創建會話生成者
            Message message = session.createTextMessage(msg);//創建消息對象
            messageProducer.send(message);//發送消息
            session.commit();
        } catch (JMSException e) {
            e.printStackTrace();
            flag = false;
        }finally {
            if(null != connection){
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }    

  這裏單獨說一下connection.createSession生成會話線程:

Session session = connection.createSession(paramA,paramB);
paramA是設置事務,paramB是設置acknowledgment mode

paramA 取值有:
1、true:支持事務
爲true時:paramB的值忽略, acknowledgment mode被jms服務器設置爲SESSION_TRANSACTED 。  
2、false:不支持事務 
爲false時:paramB的值可爲Session.AUTO_ACKNOWLEDGE、Session.CLIENT_ACKNOWLEDGE、DUPS_OK_ACKNOWLEDGE其中一個。

paramB 取值有:
1、Session.AUTO_ACKNOWLEDGE:爲自動確認,客戶端發送和接收消息不需要做額外的工作。
2、Session.CLIENT_ACKNOWLEDGE:爲客戶端確認。客戶端接收到消息後,必須調用javax.jms.Message的acknowledge方法。jms服務器纔會刪除消息。 
3、DUPS_OK_ACKNOWLEDGE:允許副本的確認模式。一旦接收方應用程序的方法調用從處理消息處返回,會話對象就會確認消息的接收;而且允許重複確認。在需要考慮資源使用時,這種模式非常有效。
4、SESSION_TRANSACTED

  到這裏我們的消息發送模塊就封裝完成,下面我們看一下消息的接收:

  原理上我們通過ConnectionFactory會話工廠 ---> 創建一個會話連接 ---> 通過會話連接創建一個會話線程 ---> 通過會話線程創建一個消息隊列 ---> 通過會話線程和消息隊列創建一個消息消費者(MessageConsumer) ---> 最後由消息消費者進行消息獲取

    /**
     * @Description 接收消息隊列中的消息
     * @param queryName 消息隊列名稱
     * @return
     *
     * @author 高尚
     * @version 1.0
     * @date 創建時間:2018年1月31日 下午4:24:14
     */
    public static void consumerGetQueryMessage(final String queryName){
        try {
            connection = factory.createConnection();//創建會話連接
            connection.start();//啓動會話連接
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            destination = session.createQueue(queryName);
            messageConsumer = session.createConsumer(destination);
            while(true){
                TextMessage message = (TextMessage) messageConsumer.receive();
                if(null != message){
                    System.out.println(queryName+"發送消息:"+message.getText());
                }
            }
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println("消費消息異常");
        }finally {
            if(null != connection){
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }

  最後單獨說一下messageConsumer.receive方法:

messageConsumer.receive();//一直等到消息
messageConsumer.receive(1000);//等到消息1秒鐘
messageConsumer.receiveNoWait();//不等待消息

  當然這樣的接收消息方式是不是感覺很low,當然我們還可以通過監聽器來實現消息接收的監聽(MessageListener),我們實現MessageListener接口,自定義消息接收監聽器:

/**
 * @Description 消息監聽器
 * @author 高尚
 * @version 1.0
 * @date 創建時間:2018年1月31日 下午4:52:36
 */
public class MsgListener implements MessageListener {
    
    /**
     * 監聽的會話隊列
     */
    private static String queryName;

    @Override
    public void onMessage(Message msg) {
        TextMessage textMsg = (TextMessage) msg;
        try {
            if(null != textMsg){
                System.out.println("【" + queryName + "】發送的消息:" + textMsg.getText());
            }
        } catch (JMSException e) {
            e.printStackTrace();
            System.out.println("獲取會話消息異常");
        }
    }

    public MsgListener(String queryName) {
        super();
        // TODO Auto-generated constructor stub
        this.queryName = queryName;
    }
    
}

  然後我們需要簡單修改一個消息接收策略:

    /**
     * @Description 通過Listener接收消息隊列中的消息
     * @param queryName 消息隊列名稱
     * @return
     *
     * @author 高尚
     * @version 1.0
     * @date 創建時間:2018年1月31日 下午4:24:14
     */
    public static void consumerGetQueryMessageListener(String queryName) {
        try {
            connection = factory.createConnection();//創建會話連接
            connection.start();//啓動會話連接
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            destination = session.createQueue(queryName);
            messageConsumer = session.createConsumer(destination);
            MsgListener msgListener = new MsgListener(queryName);
            messageConsumer.setMessageListener(msgListener);
            while(true){
                Thread.sleep(10000);
            }
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println("消費消息異常");
        }finally {
            if(null != connection){
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }

  最後我們一起看一下消息的發佈和訂閱,首先消息的發佈和訂閱與點點的消息收發基本一致,不同點在於會話線程的創建:

destination = session.createTopic(queryName);//創建消息發佈線程

  其他部分一致,沒有什麼難度,這裏不再闡述,大家可以自行測試。當然我也爲大家提供了測試參考代碼:https://github.com/hpugs/ActiveMQ

  到這裏關於ActiveMQ入門部分就和大家探討完畢,如有錯誤還有指教。謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章