ActiveMQ 入門及例項

xz43發表於2015-10-20
ActiveMQ 是Apache出品,最流行的,能力強勁的開源訊息匯流排。ActiveMQ 是一個完全支援JMS1.1和J2EE 1.4規範的 JMS Provider實現,儘管JMS規範出臺已經是很久的事情了,但是JMS在當今的J2EE應用中間仍然扮演著特殊的地位。 

ActiveMQ特性列表 

1. 多種語言和協議編寫客戶端。語言: Java、 C、 C++、 C#、 Ruby、 Perl、 Python、 PHP。應用協議: OpenWire、Stomp REST、WS Notification、XMPP、AMQP ;
2. 完全支援JMS1.1和J2EE 1.4規範 (持久化、XA訊息、事務);
3. 對Spring的支援,ActiveMQ可以很容易內嵌到使用Spring的系統裡面去,而且也支援Spring2.0的特性;
4. 通過了常見J2EE伺服器(如 Geronimo、JBoss 、 GlassFish、WebLogic)的測試,其中通過JCA 1.5 resource adaptors的配置,可以讓ActiveMQ可以自動的部署到任何相容J2EE 1.4 商業伺服器上;
5. 支援多種傳送協議:in-VM、TCP、SSL、NIO、UDP、JGroups、JXTA;
6. 支援通過JDBC和journal提供高速的訊息持久化;
7. 從設計上保證了高效能的叢集、客戶端-伺服器、點對點;
8. 支援Ajax;
9. 支援與Axis的整合;
10. 可以很容易得呼叫內嵌JMS provider,進行測試;

JMS基本概念 

JMS(Java Message Service) 即Java訊息服務。它提供標準的產生、傳送、接收訊息的介面簡化企業應用的開發。它支援兩種訊息通訊模型:點到點(point-to-point)(P2P)模型和釋出/訂閱(Pub/Sub)模型。P2P 模型規定了一個訊息只能有一個接收者;Pub/Sub 模型允許一個訊息可以有多個接收者。 
對於點到點模型,訊息生產者產生一個訊息後,把這個訊息傳送到一個Queue(佇列)中,然後訊息接收者再從這個Queue中讀取,一旦這個訊息被一個接收者讀取之後,它就在這個Queue中消失了,所以一個訊息只能被一個接收者消費。
與點到點模型不同,釋出/訂閱模型中,訊息生產者產生一個訊息後,把這個訊息傳送到一個Topic中,這個Topic可以同時有多個接收者在監聽,當一個訊息到達這個Topic之後,所有訊息接收者都會收到這個訊息。

基於JMS程式設計思路 

訊息產生者向JMS傳送訊息的步驟
(1) 建立連線使用的工廠類JMS ConnectionFactory;
(2) 使用管理物件JMS ConnectionFactory建立連線Connection;
(3) 使用連線Connection 建立會話Session;
(4) 使用會話Session和管理物件Destination建立訊息生產者MessageSender;
(5) 使用訊息生產者MessageSender傳送訊息。
訊息消費者從JMS接受訊息的步驟 
(1) 建立連線使用的工廠類JMS ConnectionFactory;
(2) 使用管理物件JMS ConnectionFactory建立連線Connection;
(3) 使用連線Connection 建立會話Session;
(4) 使用會話Session和管理物件Destination建立訊息消費者MessageReceiver;
(5) 使用訊息消費者MessageReceiver接受訊息,需要用setMessageListener將MessageListener介面繫結到MessageReceiver;
訊息消費者必須實現了MessageListener介面,需要定義onMessage事件方法。

下載安裝ActiveMQ 

去官方網站下載:http://activemq.apache.org/
解壓縮apache-activemq-5.5.1-bin.zip,然後雙擊apache-activemq-5.5.1\bin\activemq.bat執行ActiveMQ程式。(注意:要求先安裝配置好本機的JVM環境)
啟動ActiveMQ以後,登陸:http://localhost:8161/admin/,建立一個Queue,命名為FirstQueue。

ActiveMQ JMS程式碼實現 

MessageReceiver

package jms.activemq.myexample;
 
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
 
import org.apache.activemq.ActiveMQConnectionFactory;
 
public class MessageReceiver implements Runnable {
    private String url;
    private String user;
    private String password;
    private final String QUEUE;
 
    public MessageReceiver(String queue, String url, String user, String password) {
        this.url = url;
        this.user = user;
        this.password = password;
        this.QUEUE = queue;
    }
 
    @Override
    public void run() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
                user, password, url);
        Session session = null;
        Destination receiveQueue;
        try {
            Connection connection = connectionFactory.createConnection();
 
            session = connection
                    .createSession(true, Session.SESSION_TRANSACTED);
            receiveQueue = session.createQueue(QUEUE);
            MessageConsumer consumer = session.createConsumer(receiveQueue);
 
            connection.start();
 
            while (true) {
                Message message = consumer.receive();
 
                if (message instanceof TextMessage) {
                    TextMessage receiveMessage = (TextMessage) message;
                    System.out.println("我是Receiver,收到訊息如下: \r\n"
                            + receiveMessage.getText());
                } else {
                    session.commit();
                    break;
                }
 
            }
            connection.close();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
 
    public String getUrl() {
        return url;
    }
 
    public void setUrl(String url) {
        this.url = url;
    }
 
    public String getUser() {
        return user;
    }
 
    public void setUser(String user) {
        this.user = user;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    } 
 
}


MessageSender

package jms.activemq.myexample;
 
import java.util.Date;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
  
public class MessageSender implements Runnable {
     
    private String url;
    private String user;
    private String password;
    private final String QUEUE;
 
    public MessageSender(String queue, String url, String user, String password) {
        this.url = url;
        this.user = user;
        this.password = password;
        this.QUEUE = queue;
    }
 
    @Override
    public void run() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
                user, password, url);
        Session session = null;
        Destination sendQueue;
        Connection connection = null;
 
        int messageCount = 0;
        try {
            connection = connectionFactory.createConnection();
 
            connection.start();
 
            while (true) {
                session = connection.createSession(true,
                        Session.SESSION_TRANSACTED);
 
                sendQueue = session.createQueue(QUEUE);
                MessageProducer sender = session.createProducer(sendQueue);
                TextMessage outMessage = session.createTextMessage();
                outMessage.setText(new Date() + "現在傳送是第" + messageCount + "條訊息");
 
                sender.send(outMessage);
 
                session.commit();
 
                sender.close();
 
                if ((++messageCount) == 10) {
                    // 發夠十條訊息退出
                    break;
                }
                Thread.sleep(1000);
            }
            connection.close();
        } catch (JMSException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
 
    public String getUrl() {
        return url;
    }
 
    public void setUrl(String url) {
        this.url = url;
    }
 
    public String getUser() {
        return user;
    }
 
    public void setUser(String user) {
        this.user = user;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
}


MyActiveMQDemo


package jms.activemq.myexample;
 
public class MyActiveMQDemo {
    public static void main(String[] args) {
        String url = "tcp://localhost:61616";
        String user = null;
        String password = null;
        String query = "MyQueue";         
         
        new Thread(new MessageSender(query,url,user,password), "Test-Sender").start();
        new Thread(new MessageReceiver(query,url,user,password), "Test-Receiver").start();
    }
}

可以把上面獲得連線的通用部分提取出來,構造一個專門的類來管理


import java.io.IOException;  
import java.io.InputStream;  
import java.util.Properties;  
  
import javax.jms.Connection;  
import javax.jms.JMSException;  
import javax.jms.MessageConsumer;  
import javax.jms.MessageProducer;  
import javax.jms.Session;  
  
import org.apache.activemq.ActiveMQConnectionFactory;  
  
/** 
 * 管理伺服器連線 
 *  
 */  
  
public class ConnectionManager {  
  
    private String url;                 //遠端伺服器地址   
    private String queue;               //訊息佇列名  
    private String username;                //用於連線伺服器的使用者名稱  
    private String password;                //用於連線伺服器的密碼  
    private final String URL = "url";           //properties檔案中url的key  
    private final String QUEUE = "queue";       //properties檔案中query的key  
    private final String USERNAME = "username"; //properties檔案中username的key  
    private final String PASSWORD = "password"; //properties檔案中password的key  
    private final String FILEPATH = "/connection.properties";  
      
    /** 
     * 初始化連線字串 
     * @return 是否初始化成功 
     */  
    public Boolean init() {  
        Properties properties = new Properties();  
        InputStream inputStream = Object.class.getResourceAsStream(FILEPATH);  
        if (inputStream != null) {  
            try {  
                properties.load(inputStream);  
                url = properties.getProperty(URL);  
                queue = properties.getProperty(QUEUE);  
                username = properties.getProperty(USERNAME);  
                password = properties.getProperty(PASSWORD);  
                inputStream.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            return true;  
        } else {  
        }  
        return false;  
    }  
      
    /** 
     * 與遠端伺服器取得連線 
     * @param url           伺服器連線地址 
     * @param username      使用者名稱 
     * @param password      密碼 
     * @return              連線物件 
     * @throws JMSException JMS異常S 
     */  
    public Connection getConnection() {  
        Connection connection = null;  
        if (init()) {  
            ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(url);  
            try {  
                connection = factory.createConnection(username, password);  
            } catch (JMSException e) {  
                e.printStackTrace();  
            }  
        }  
        return connection;  
    }  
      
    /** 
     * 關閉連線 
     * @param connection    與遠端伺服器連線 
     * @throws JMSException JMS異常 
     */  
    public void closeConnection(Connection connection, Session session,  
            MessageProducer producer, MessageConsumer consumer) {  
        try {  
            if (producer != null) {  
                producer.close();  
            }  
            if (consumer != null) {  
                consumer.close();  
            }  
            if (session != null) {  
                session.close();  
            }  
            if (connection != null) {  
                connection.close();  
            }  
        } catch (JMSException e) {  
            e.printStackTrace();  
        }  
    }  
  
    /** 
     * 取得佇列名 
     * @return 佇列名 
     */  
    public String getQueue() {  
        init();  
        return queue;  
    }  
  
}  


Spring +ActiveMQ 的JMS程式碼實現 


所需jar 

activemq-all-5.6.0.jar
commons-logging-1.1.1.jar
log4j-1.2.17.jar
org.springframework.asm-3.1.0.RELEASE.jar
org.springframework.beans-3.1.0.RELEASE.jar
org.springframework.context-3.1.0.RELEASE.jar
org.springframework.core-3.1.0.RELEASE.jar
org.springframework.expression-3.1.0.RELEASE.jar
org.springframework.jms-3.1.0.RELEASE.jar
org.springframework.transaction-3.1.0.RELEASE.jar

spring配置檔案applicationContext.xml 



這時主要是配置activemq服務資訊與實現springjms的對應介面 


訊息產生者 

Java程式碼 

package test; 

import javax.jms.JMSException; 

import javax.jms.Message; 

import javax.jms.Session; 

 

import org.springframework.jms.core.MessageCreator; 

 

/**

 * 訊息產生者

 * User

 * Time: 12-6-14 上午11:31

 */ 

public class MyMessageCreator implements MessageCreator { 

    public int n = 0; 

    private static String str1 = "這個是第 "; 

    private static String str2 = " 個測試訊息!"; 

    private String str = ""; 

    @Override 

    public Message createMessage(Session paramSession) throws JMSException { 

        System.out.println("MyMessageCreator  n=" + n); 

        if (n == 9) { 

            //在這個例子中表示第9次呼叫時,傳送結束訊息 

            return paramSession.createTextMessage("end"); 

        } 

        str = str1 + n + str2; 

        return paramSession.createTextMessage(str); 

    } 

傳送訊息方 

Java程式碼 

package test; 

import javax.jms.Destination; 

 

import org.springframework.context.ApplicationContext; 

import org.springframework.context.support.ClassPathXmlApplicationContext; 

import org.springframework.jms.core.JmsTemplate; 

/**

 * 傳送訊息方

 * User

 * Time: 12-6-14 上午11:29

 */

public class MessageSender extends Thread {

    public static void main(String args[]) throws Exception {

        String[] configLocations = new String[] {"test/applicationContext.xml"};

        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);

        JmsTemplate jmsTemplate = (JmsTemplate) context.getBean("jmsTemplate");

        Destination destination = (Destination) context.getBean("destination");

        for (int i = 1; i < 100; i++) {

            System.out.println("傳送 i=" + i);

            //訊息產生者

            MyMessageCreator myMessageCreator = new MyMessageCreator();

            myMessageCreator.n = i;

            jmsTemplate.send(destination, myMessageCreator);

            sleep(10000);//10秒後傳送下一條訊息

        }

    }

}


訊息接收方 

Java程式碼 

package test; 

import javax.jms.Destination; 

import javax.jms.TextMessage; 

 

import org.springframework.context.ApplicationContext; 

import org.springframework.context.support.ClassPathXmlApplicationContext; 

import org.springframework.jms.core.JmsTemplate; 

/**

 * 訊息接收方

 * User

 * Time: 12-6-14 上午11:32

 */ 

public class MessageReciver{ 

    public static void main(String args[]) throws Exception { 

        String[] configLocations = new String[] {"test/applicationContext.xml"}; 

        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations); 

 

        JmsTemplate jmsTemplate = (JmsTemplate) context.getBean("jmsTemplate"); 

        Destination destination = (Destination) context.getBean("destination"); 

 

        TextMessage msg = null; 

        //是否繼續接收訊息 

        boolean isContinue = true; 

        while (isContinue) { 

            msg = (TextMessage) jmsTemplate.receive(destination); 

            System.out.println("收到訊息 :" + msg.getText()); 

            if (msg.getText().equals("end")) { 

                isContinue = false; 

                System.out.println("收到退出訊息,程式要退出!"); 

            } 

        } 

        System.out.println("程式退出了!"); 

    } 

}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-1815168/,如需轉載,請註明出處,否則將追究法律責任。

相關文章