ActiveMQ

一、ActiveMQ安裝

1.windows安裝

首先去http://activemq.apache.org/download.html 下載最新版本
目錄如下:
+bin (windows下面的bat和unix/linux下面的sh)
+conf (activeMQ配置目錄,包含最基本的activeMQ配置文件)
+data (默認是空的)
+docs (index,replease版本里面沒有文檔,-.-b不知道爲啥不帶)
+example (幾個例子)
+lib (activemMQ使用到的lib)
-apache-activemq-4.1-incubator.jar (ActiveMQ的binary)
-LICENSE.txt
運行信息
運行信息
-NOTICE.txt
-README.txt
-user-guide.html
這裏寫圖片描述
啓動bin/win64/activemq.bat
啓動成功就可以訪問管理員界面:http://localhost:8161/admin

默認用戶名和密碼admin/admin。如果你想修改用戶名和密碼的話,在conf/jetty-realm.properties中修改即可。

2.Linux安裝

wget http://archive.apache.org/dist/activemq/5.14.1/apache-activemq-5.14.1-bin.tar.gz
cd apache-activemq-5.14.1/bin/linux-x86-64/
./activemq start

二、ActiveMQ應用

1.點對點方式(point to point Queue)

  點對點的消息發送方式主要建立在 Message Queue,Sender,reciever上,Message Queue 存貯消息,Sneder 發送消息,receive接收消息.具體點就是Sender Client發送Message Queue ,而 receiver Cliernt從Queue中接收消息和”發送消息已接受”到Quere,確認消息接收。消息發送客戶端與接收客戶端沒有時間上的依賴,發送客戶端可以在任何時刻發送信息到Queue,而不需要知道接收客戶端是不是在運行

2.發佈/訂閱方式(public/subscriber Messaging Topic)

   發佈/訂閱方式用於多接收客戶端的方式.作爲發佈訂閱的方式,可能存在多個接收客戶端,並且接收端客戶端與發送客戶端存在時間上的依賴。一個接收端只能接收他創建以後發送客戶端發送的信息。作爲subscriber ,在接收消息時有兩種方法,destination的receive方法,和實現message listener 接口的onMessage 方法。

發送消息的基本步驟:

  • 創建連接使用的工廠類JMS ConnectionFactory
  • 使用管理對象JMS ConnectionFactory建立連接Connection,並啓動
  • 使用連接Connection 建立會話Session
  • 使用會話Session和管理對象Destination創建消息生產者MessageSender
  • 使用消息生產者MessageSender發送消息

消息接收者從JMS接受消息的步驟 :

  • 創建連接使用的工廠類JMS ConnectionFactory
  • 使用管理對象JMS ConnectionFactory建立連接Connection,並啓動
  • 使用連接Connection 建立會話Session
  • 使用會話Session和管理對象Destination創建消息接收者MessageReceiver
  • 使用消息接收者MessageReceiver接受消息,需要用setMessageListener將MessageListener接口綁定到MessageReceiver消息接收者必須實現了MessageListener接口,需要定義onMessage事件方法。
    這裏寫圖片描述

3.JMS方式

接受者

public class MessageReceiver {
    // tcp 地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    // 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
    public static final String DESTINATION = "hoo.mq.queue";
    public static void run() throws Exception {
        Connection connection = null;
        Session session = null;
        try {
            // 創建鏈接工廠
            ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            // 通過工廠創建一個連接
            connection = factory.createConnection();
            // 啓動連接
            connection.start();
            // 創建一個session會話
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            // 創建一個消息隊列
            Destination destination = session.createQueue(DESTINATION);
            // 創建消息製作者
            MessageConsumer consumer = session.createConsumer(destination);
            while (true) {
                // 接收數據的時間(等待) 100 ms
                Message message = consumer.receive(1000 * 100);

                TextMessage text = (TextMessage) message;
                if (text != null) {
                    System.out.println("接收:" + text.getText());
                } else {
                    break;
                }
            }
            // 提交會話
            session.commit();
        } catch (Exception e) {
            throw e;
        } finally {
            // 關閉釋放資源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }    

    public static void main(String[] args) throws Exception {
        MessageReceiver.run();
    }
}

發送者

public class MessageSender {
    // 發送次數
    public static final int SEND_NUM = 5;
    // tcp 地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    // 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
    public static final String DESTINATION = "hoo.mq.queue";
    @SuppressWarnings("unused")
    private static void sendMessage(Session session, MessageProducer producer) throws JMSException{
        for (int i = 0; i < SEND_NUM; i++) {
            String message = "發送消息第" + (i + 1) + "條";
            TextMessage text = session.createTextMessage(message);

            System.out.println(message);
            producer.send(text);
        }       
    }

    public static void run() throws Exception {
        Connection connection = null;
        Session session = null;
        try {
            // 創建鏈接工廠
            ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            // 通過工廠創建一個連接
            connection = factory.createConnection();
            // 啓動連接
            connection.start();
            // 創建一個session會話
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            // 創建一個消息隊列
            Destination destination = session.createQueue(DESTINATION);
            // 創建消息製作者
            MessageProducer producer = session.createProducer(destination);
            // 設置持久化模式
            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            sendMessage(session, producer);
            // 提交會話
            session.commit();

        } catch (Exception e) {
            throw e;
        } finally {
            // 關閉釋放資源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }   
    public static void main(String[] args) {
        try {
            MessageSender.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Queue方式

接受者

public class QueueReceiver {
    // tcp 地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    // 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
    public static final String TARGET = "test.queue";
    public static void run() throws Exception {
        QueueConnection connection = null;
        QueueSession session = null;
        try {
            // 創建鏈接工廠
            QueueConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            // 通過工廠創建一個連接
            connection = factory.createQueueConnection();
            // 啓動連接
            connection.start();
            // 創建一個session會話
            session = connection.createQueueSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            // 創建一個消息隊列
            Queue queue = session.createQueue(TARGET);
            // 創建消息製作者
            javax.jms.QueueReceiver receiver = session.createReceiver(queue);

            receiver.setMessageListener(new MessageListener() { 
                public void onMessage(Message msg) { 
                    if (msg != null) {
                        MapMessage map = (MapMessage) msg;
                        try {
                            System.out.println(map.getLong("time") + "接收#" + map.getString("text"));
                        } catch (JMSException e) {
                            e.printStackTrace();
                        }
                    }
                } 
            }); 
            // 休眠100ms再關閉
            Thread.sleep(1000 * 100); 
            // 提交會話
            session.commit();
        } catch (Exception e) {
            throw e;
        } finally {
            // 關閉釋放資源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        QueueReceiver.run();
    }
}

發送者

public class QueueSender {
    // 發送次數
    public static final int SEND_NUM = 5;
    // tcp 地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    // 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
    public static final String DESTINATION = "test.queue";
    public static void sendMessage(QueueSession session, javax.jms.QueueSender sender) throws Exception {
        for (int i = 0; i < SEND_NUM; i++) {
            String message = "發送消息第" + (i + 1) + "條";

            MapMessage map = session.createMapMessage();
            map.setString("text", message);
            map.setLong("time", System.currentTimeMillis());
            System.out.println(map);

            sender.send(map);
        }
    }

    public static void run() throws Exception {
        QueueConnection connection = null;
        QueueSession session = null;
        try {
            // 創建鏈接工廠
            QueueConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            // 通過工廠創建一個連接
            connection = factory.createQueueConnection();
            // 啓動連接
            connection.start();
            // 創建一個session會話
            session = connection.createQueueSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            // 創建一個消息隊列
            Queue queue = session.createQueue(DESTINATION);
            // 創建消息發送者
            javax.jms.QueueSender sender = session.createSender(queue);
            // 設置持久化模式
            sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            sendMessage(session, sender);
            // 提交會話
            session.commit();

        } catch (Exception e) {
            throw e;
        } finally {
            // 關閉釋放資源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }
    public static void main(String[] args) throws Exception {
        QueueSender.run();
    }
}

topic方式

接受者

public class TopicReceiver {
    // tcp 地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    // 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
    public static final String TARGET = "hoo.mq.topic";

    public static void run() throws Exception {
        TopicConnection connection = null;
        TopicSession session = null;
        try {
            // 創建鏈接工廠
            TopicConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            // 通過工廠創建一個連接
            connection = factory.createTopicConnection();
            // 啓動連接
            connection.start();
            // 創建一個session會話
            session = connection.createTopicSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            // 創建一個消息隊列
            Topic topic = session.createTopic(TARGET);
            // 創建消息製作者
            TopicSubscriber subscriber = session.createSubscriber(topic);

            subscriber.setMessageListener(new MessageListener() { 
                public void onMessage(Message msg) { 
                    if (msg != null) {
                        MapMessage map = (MapMessage) msg;
                        try {
                            System.out.println(map.getLong("time") + "接收#" + map.getString("text"));
                        } catch (JMSException e) {
                            e.printStackTrace();
                        }
                    }
                } 
            }); 
            // 休眠100ms再關閉
            Thread.sleep(1000 * 100); 
            // 提交會話
            session.commit();

        } catch (Exception e) {
            throw e;
        } finally {
            // 關閉釋放資源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        TopicReceiver.run();
    }
}

發送者

public class TopicSender {
    // 發送次數
    public static final int SEND_NUM = 5;
    // tcp 地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    // 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
    public static final String DESTINATION = "hoo.mq.topic";
    public static void sendMessage(TopicSession session, TopicPublisher publisher) throws Exception {
        for (int i = 0; i < SEND_NUM; i++) {
            String message = "發送消息第" + (i + 1) + "條";

            MapMessage map = session.createMapMessage();
            map.setString("text", message);
            map.setLong("time", System.currentTimeMillis());
            System.out.println(map);

            publisher.send(map);
        }
    }

    public static void run() throws Exception {

        TopicConnection connection = null;
        TopicSession session = null;
        try {
            // 創建鏈接工廠
            TopicConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            // 通過工廠創建一個連接
            connection = factory.createTopicConnection();
            // 啓動連接
            connection.start();
            // 創建一個session會話
            session = connection.createTopicSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            // 創建一個消息隊列
            Topic topic = session.createTopic(DESTINATION);
            // 創建消息發送者
            TopicPublisher publisher = session.createPublisher(topic);
            // 設置持久化模式
            publisher.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            sendMessage(session, publisher);
            // 提交會話
            session.commit();
        } catch (Exception e) {
            throw e;
        } finally {
            // 關閉釋放資源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        TopicSender.run();
    }
}

四、整合activeMQ

集成spring:引入jar包

<dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-all</artifactId>
        <version>5.14.1</version>
     </dependency> 
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
        <version>4.0.8.RELEASE</version>
     </dependency>
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-messaging</artifactId>
        <version>4.0.8.RELEASE</version>
     </dependency>   
     <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-spring</artifactId>
        <version>5.14.1</version>
     </dependency> 

配置文件spring-context-activemq.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"  
    xmlns:jms="http://www.springframework.org/schema/jms"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd     
        http://www.springframework.org/schema/context     
        http://www.springframework.org/schema/context/spring-context-4.0.xsd  
        http://www.springframework.org/schema/jms  
        http://www.springframework.org/schema/jms/spring-jms-4.0.xsd  
        http://activemq.apache.org/schema/core  
        http://activemq.apache.org/schema/core/activemq-core-5.14.1.xsd"> 
        <description>spring-activeMQ</description>
    <!-- 獲取ActiveMQ提供的ConnectionFactory -->
    <amq:connectionFactory id="amqConnectionFactory" brokerURL="tcp://127.0.0.1:61616" userName="admin" password="admin"></amq:connectionFactory>

    <!-- spring連接activeMQ的conneciotnFactory --> 
    <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
        <constructor-arg ref="amqConnectionFactory"></constructor-arg>
        <property name="sessionCacheSize" value="100" />  
    </bean>

    <!-- 定義JmsTemplate的Queue類型 -->
    <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">  
        <!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->    
        <constructor-arg ref="connectionFactory"></constructor-arg>
        <!-- 非pub/sub模型(發佈/訂閱),即隊列模式 -->  
        <property name="pubSubDomain" value="false" />  
    </bean> 

    <!-- 定義JmsTemplate的Topic類型 -->  
    <bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">  
        <!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->    
        <constructor-arg ref="connectionFactory"></constructor-arg>
        <!-- pub/sub模型(發佈/訂閱) -->  
        <property name="pubSubDomain" value="true" />  
    </bean>


    <bean id="queueReceiver" class="com.drink.modules.activemq.QueueReceiver"></bean>
    <!-- 定義Queue監聽器 -->  
    <jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">  
        <jms:listener destination="test.queue" ref="queueReceiver"/>  
    </jms:listener-container>  

    <bean id="topicReceiver" class="com.drink.modules.activemq.TopicReceiver"></bean>
    <!-- 定義Topic監聽器 -->  
    <jms:listener-container destination-type="topic" container-type="default" connection-factory="connectionFactory" acknowledge="auto">  
        <jms:listener destination="test.topic" ref="topicReceiver"/>  
    </jms:listener-container>               
</beans>

Queue接收文件:

public class QueueReceiver implements MessageListener {
    @Override
    public void onMessage(Message message) {
         try {
            System.out.println("QueueReceiver接收到消息:"+((TextMessage)message).getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }       
    }
}

Topic接收文件:

public class TopicReceiver implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
            System.out.println("TopicReceiver接收到消息:"+((TextMessage)message).getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }       
    }
}

Queue發送文件:

@Component("queueSender") 
public class QueueSender {
    @Autowired
    @Qualifier("jmsQueueTemplate")
    private JmsTemplate jmsTemplate; 

    public void send(String queueName, final String message){
        jmsTemplate.send(queueName,new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage(message);
            }
        });
    }
}

Topic發送文件:

@Component("topicSender")
public class TopicSender {
    @Autowired  
    @Qualifier("jmsTopicTemplate")  
    private JmsTemplate jmsTemplate; 
    public void send(String queueName, final String message){
        jmsTemplate.send(queueName,new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage(message);
            }
        });
    }
}

持久化到數據配置

在mysql中手動創建一個名稱爲activemq的數據庫,注意編碼格式。
將mysql驅動的jar包拷貝到apache-activemq-5.14.1\lib目錄下
修改conf下的activemq.xml文件
將默認的

<jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="true" />  

修改爲

<!--createTablesOnStartup首次啓動創建表時設置爲true,其餘情況改爲false-->
<jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="true"/>

在broker節點後添加數據源

<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> 
<property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
<property name="url" value="jdbc:mysql://localhost/activemq"/> 
<property name="username" value="root"/> 
<property name="password" value="123456"/> 
<property name="poolPreparedStatements" value="true"/> 
</bean> 

注意:這裏的版本是5.14.1,dbcp的包是commons-dbcp2-2.1.1.jar,所以這裏的classorg.apache.commons.dbcp2.BasicDataSource;
低版本的MQ配置爲org.apache.commons.dbcp.BasicDataSource

首次啓動後就會看到數據庫的創建的三張表
這裏寫圖片描述

編碼中發送者需要設置持久化的方式

 // 創建消息發送者
        javax.jms.QueueSender sender = session.createSender(queue);
        // 設置持久化模式
        sender.setDeliveryMode(DeliveryMode.PERSISTENT);

spring中在JmsTemplate模板配置中設置

<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">  
    <!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->    
    <constructor-arg ref="connectionFactory"></constructor-arg>
    <!-- 非pub/sub模型(發佈/訂閱),即隊列模式 -->  
    <property name="pubSubDomain" value="false" />  
    <!--1爲非持久化,2爲持久化-->
    <property name="deliveryMode" value="2" /> 
</bean> 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章