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


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