ActiveMQ入門實例

一、代碼結構

使用Maven管理代碼,導入ActiveMQ的包

<dependency>
		  <groupId>org.apache.activemq</groupId>
		  <artifactId>activemq-core</artifactId>
		  <version>5.7.0</version>
</dependency>

二、openwire協議通信

1、Producer:

package com.xuwei.activemq;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Sender {
    private static final int SEND_NUMBER = 5;

    public static void main(String[] args) {
        // ConnectionFactory :連接工廠,JMS 用它創建連接
        ConnectionFactory connectionFactory;
        // Connection :JMS 客戶端到JMS Provider 的連接
        Connection connection = null;
        // Session: 一個發送或接收消息的線程
        Session session;
        // Destination :消息的目的地;消息發送給誰.
        Destination destination;
        // MessageProducer:消息發送者
        MessageProducer producer;
        // TextMessage message;
        // 構造ConnectionFactory實例對象,此處採用ActiveMq的實現jar
        connectionFactory = new ActiveMQConnectionFactory(
                ActiveMQConnection.DEFAULT_USER,
                ActiveMQConnection.DEFAULT_PASSWORD,
                "tcp://localhost:61616");
        try {
            // 構造從工廠得到連接對象
            connection = connectionFactory.createConnection();
            // 啓動
            connection.start();
            // 獲取操作連接
            session = connection.createSession(Boolean.TRUE,
                    Session.AUTO_ACKNOWLEDGE);
            // 獲取session注意參數值xingbo.xu-queue是一個服務器的queue,須在在ActiveMq的console配置
            destination = session.createQueue("FirstQueue");
            //destination = session.createTopic("FirstTopic");//主題
            // 得到消息生成者【發送者】
            producer = session.createProducer(destination);
            // 設置不持久化,此處學習,實際根據項目決定
            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            // 構造消息,此處寫死,項目就是參數,或者方法獲取
            sendMessage(session, producer);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != connection)
                    connection.close();
            } catch (Throwable ignore) {
            }
        }
    }

    public static void sendMessage(Session session, MessageProducer producer)
            throws Exception {
        for (int i = 1; i <= SEND_NUMBER; i++) {
            TextMessage message = session
                    .createTextMessage("ActiveMq 發送的消息" + i);
            // 發送消息到目的地方
            System.out.println("發送消息:" + "ActiveMq 發送的消息" + i);
            producer.send(message);
        }
    }
}

2、Consumer:

package com.xuwei.activemq;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Receiver {
    public static void main(String[] args) {
        // ConnectionFactory :連接工廠,JMS 用它創建連接
        ConnectionFactory connectionFactory;
        // Connection :JMS 客戶端到JMS Provider 的連接
        Connection connection = null;
        // Session: 一個發送或接收消息的線程
        Session session;
        // Destination :消息的目的地;消息發送給誰.
        Destination destination;
        // 消費者,消息接收者
        MessageConsumer consumer;
        connectionFactory = new ActiveMQConnectionFactory(
                ActiveMQConnection.DEFAULT_USER,
                ActiveMQConnection.DEFAULT_PASSWORD,
                "tcp://localhost:61616");
        try {
            // 構造從工廠得到連接對象
            connection = connectionFactory.createConnection();
            // 啓動
            connection.start();
            // 獲取操作連接
            session = connection.createSession(Boolean.FALSE,
                    Session.AUTO_ACKNOWLEDGE);
            // 獲取session注意參數值xingbo.xu-queue是一個服務器的queue,須在在ActiveMq的console配置
            destination = session.createQueue("FirstQueue");
            consumer = session.createConsumer(destination);
            /*
            connection.setClilentID("client_001");
            Topic topic = session.createTopic("FirstTopic");
            consumer = session.createDurableSubscriber(topic, "client_001");//訂閱主題
            */
            while (true) {
                //設置接收者接收消息的時間,爲了便於測試,這裏誰定爲100s
                TextMessage message = (TextMessage) consumer.receive(100000);
                if (null != message) {
                    System.out.println("收到消息" + message.getText());
                } else {
                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != connection)
                    connection.close();
            } catch (Throwable ignore) {
            }
        }
    }
}

另外,消費者可以通過事件監聽的方式來處理消息,上面 while (true) { ... } 部分修改爲:

...

consumer.setMessageLisener(new MessageListener() {
    @Override
    public viod onMessage(Message message)
    {
        try{
            TextMessage txtMessage = (TextMessage) message;
            if(null != txtMessage) {
                String msg = txtMessage.getText();
                System.out.println(msg);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

}
});
...



三、與Spring整合

1、生產者

Spring配置:

<!-- 創建工廠連接 -->
	<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://localhost:61616" />
	</bean>
	
	
	<!-- activeMQ消息目標 隊列 -->
	<bean id="rantzDestination" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg index="0" value="rantz.marketing.queue"></constructor-arg>
	</bean>
	
	<!-- activeMQ消息目標 主題-->
        <!--	<bean id="rantzDestination" class="org.apache.activemq.command.ActiveMQTopic">-->
        <!--		<constructor-arg index="0" value="rantz.marketing.queue"></constructor-arg>-->
        <!--	</bean>-->
	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
	</bean>
	
	<bean id="marketingGateway" class="com.jms.service.RantzMarketingGatewayImpl">
		<property name="jmsTemplate" ref="jmsTemplate" />
		<property name="destination" ref="rantzDestination" />
	</bean>
主程序:

public static void main(String[] args) {
		/*開始加載spring配置文件*/
			ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
			IRantzMarketingGateway rantzMarketingGateway= (RantzMarketingGatewayImpl) context.getBean("marketingGateway");
			rantzMarketingGateway.sendMotoristInfo();
			System.out.println("Start ...");
		}
消息發送類:

                import javax.jms.Destination;
		import javax.jms.JMSException;
		import javax.jms.Message;
		import javax.jms.Session;
		import org.springframework.jms.core.JmsTemplate;
		import org.springframework.jms.core.MessageCreator;
		public class RantzMarketingGatewayImpl implements IRantzMarketingGateway {
			
			private JmsTemplate jmsTemplate;
			private Destination destination;
			
			public JmsTemplate getJmsTemplate() {
				return jmsTemplate;
			}
			public void setJmsTemplate(JmsTemplate jmsTemplate) {
				this.jmsTemplate = jmsTemplate;
			}
			public Destination getDestination() {
				return destination;
			}
			public void setDestination(Destination destination) {
				this.destination = destination;
			}
			
			public void sendMotoristInfo(){
				jmsTemplate.send(
					destination,
					new MessageCreator(){
						public Message createMessage(Session session) throws JMSException {
							return session.createTextMessage("這是一個測試");
						}
					}
				);
			}
		}

2、消費者

Spring配置:

	<!-- 創建工廠連接 -->
	<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://localhost:61616" />
	</bean>
	
	<!-- activeMQ消息目標 隊列 -->
	<bean id="rantzDestination" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg index="0" value="rantz.marketing.queue"></constructor-arg>
	</bean>
	
	<!-- activeMQ消息目標 主題-->
	<!--	<bean id="rantzDestination" class="org.apache.activemq.command.ActiveMQTopic">-->
	<!--		<constructor-arg index="0" value="rantz.marketing.queue"></constructor-arg>-->
	<!--	</bean>-->
	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="defaultDestination" ref="rantzDestination" />
	</bean>
	
	<bean id="marketingGateway" class="com.huateng.jms.service.MarketingReceiverGatewayImpl">
		<property name="jmsTemplate" ref="jmsTemplate" />
	</bean>
主程序:

	public static void main(String[] args) {
		/*開始加載spring配置文件*/
			ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
			MarketingReceiverGatewayImpl rantzMarketingGateway= (MarketingReceiverGatewayImpl) context.getBean("marketingGateway");
			System.out.println("Receive Start ...");
			try {
				rantzMarketingGateway.receiveMotorist();
			} catch (Exception e) {
				e.printStackTrace();
			}
	    }
消息接收類:

import javax.jms.TextMessage;
import org.springframework.jms.core.JmsTemplate;
public class MarketingReceiverGatewayImpl {
	
	private JmsTemplate jmsTemplate;
	
	public JmsTemplate getJmsTemplate() {
		return jmsTemplate;
	}
	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}
	
	public MarketingReceiverGatewayImpl() {
	}
	
	public void receiveMotorist() throws Exception{
		TextMessage message  = (TextMessage)jmsTemplate.receive();
		System.out.println("reviced msg is:" + message.getText());
	}
	
}


四、Stomp協議通信

1、資源地址

    1)Stomp協議實現:http://stomp.github.io/implementations.html

    2)Stomp協議AS3實現:as3-storm

2、生產者(Java)

修改Openwire協議示例中的生產者代碼:

    public static void sendMessage(Session session, MessageProducer producer)
            throws Exception {
        for (int i = 1; i <= SEND_NUMBER; i++) {
            String msg = "ActiveMq 發送的消息" + i;
            TextMessage message = session.createByteMessage();
            message.writeUTF(msg);
            System.out.println(msg);
            producer.send(message);
        }
    }

3、消費者(Flex)

...

<mx:Script>
import flash.utils.ByteArray;

import org.codehaus.stomp.event.MessageEvent;
import org.codehaus.stomp.headers.ConnectHeaders;

private var destination:String = "/queue/FirstQueue"; //"/queue"打頭表示隊列;"/topic"打頭表示主題

private function init():void
{
	var ch:ConnectHeaders = new ConnectHeaders();
	ch.login= = "guest";
	ch.passcode = "guest";
	stomp.connect("localhost", 61613, ch);
	stomp.subscribe(destination);
}

private function handleMessages(event:MessageEvent):void
{
	var bytes:ByteArray = event.message.body;
	var s:String = bytes.readUTF();
	trace("收到消息" + s);
}
</mx:Script>

<stomp:Stomp id="stomp" message="handleMessages(event)"/>

...


五、測試

以(二)中示例程序測試。

1、P2P模式(Queue)

測試一:

A、 先運行Sender類,待運行完畢後,運行Receiver類
B、 在此過程中activemq數據庫的activemq_msgs表中沒有數據
C、 再次運行Receiver,消費不到任何信息

測試二:

A、  先運行Sender類
B、 重啓電腦
C、 運行Receiver類,無任何信息被消費

測試三:

A、   把Sender類中的producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);改爲producer.setDeliveryMode(DeliveryMode.PERSISTENT);
B、   先運行Sender類,待運行完畢後,運行Receiver類
C、   在此過程中activemq數據庫的activemq_msgs表中有數據生成,運行完Receiver類後,數據清除

測試四:

A、    把Sender類中的producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);改爲producer.setDeliveryMode(DeliveryMode.PERSISTENT);
B、    運行Sender類
C、    重啓電腦
D、    運行Receiver類,有消息被消費

結論:   
通過以上測試,可以發現,在P2P類型中當DeliveryMode設置爲NON_PERSISTENCE時,消息被保存在內存中,而當DeliveryMode設置爲PERSISTENCE時,消息保存在broker的相應的文件或者數據庫中。而且P2P中消息一旦被Consumer消費就從broker中刪除。

2、Pub/Sub模式(Topic)

測試一:

A、先啓動Sender類
B、再啓動Receiver類
C、結果無任何記錄被訂閱

測試二:

A、先啓動Receiver類,讓Receiver在相關主題上進行訂閱
B、停止Receiver類,再啓動Sender類
C、待Sender類運行完成後,再啓動Receiver類
D、結果發現相應主題的信息被訂閱

Ø   


參考:

http://www.cnblogs.com/xwdreamer/archive/2012/02/21/2360818.html

http://blog.csdn.net/xueyepiaoling/article/details/6321100

http://itindex.net/detail/44553-activemq


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