[ActiveMQ实战]基于JMS的pub/sub传播机制

     上篇博客介绍了activemq基于JMS的点对点消息传播机制的实现,这里介绍另一个发布/订阅方式实现。

一、发布订阅模型

    就像订阅报纸。我们可以选择一份或者多份报纸,比如:北京日报、人民日报。这些报纸就相当于发布订阅模型中的topic。如果有很多人订阅了相同的报纸,那我们就在同一个topic中注册,对于报纸发行方,它就和所有的订阅者形成了一对多的关系。如下:

 

二、发布者的实现

package com.tgb.activemqTopic;

import java.awt.font.TextMeasurer;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息发布者
 * @author xx
 *
 */
public class JMSProducer {
	//默认连接用户名
	private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
	//默认连接密码
	private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
	//默认的连接地址
	private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL;
	//发送的消息数量
	private static final int SENNUM = 10;
	
	public static void main(String[] args){
		ConnectionFactory factory ; //连接工厂
		Connection connection = null ; //连接
		Session session ; //会话,接收或者发送消息的线程
		Destination destination; //消息的目的地
		MessageProducer messageProducer; //消息生产者
		//实例化连接工厂
		factory = new ActiveMQConnectionFactory(JMSProducer.USERNAME, JMSProducer.PASSWORD, JMSProducer.BROKEURL);
		//通过连接工厂获取connection
		try {
			connection = factory.createConnection();
			connection.start(); //启动连接
			//创建session
			session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
			//创建消息队列
//			destination = session.createQueue("FirstQueue");
			
			//创建主题
			destination = session.createTopic("topic1");
			//创建消息发布者
			messageProducer = session.createProducer(destination);
			//发送消息
			sendMessage(session, messageProducer);
			session.commit();
		} catch (JMSException e) {
			e.printStackTrace();
		}finally{
			if (connection != null) {
				try {
					connection.close();
				} catch (JMSException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 发送消息
	 * @param session
	 * @param mp
	 * @throws JMSException 
	 */
	public static void sendMessage(Session session, MessageProducer mp) throws JMSException{
		for(int i = 0;i<JMSProducer.SENNUM;i++){
			TextMessage message = session.createTextMessage("ActiveMq 发布的消息" + i);
			System.out.println("发布消息:" + "ActiveMq 发布的消息" + i);
			mp.send(message);
		}
	}
}

   这里和点对点的不同就是不再是创建消息队列,而是创建topic。而且也不是消息生产者而是发布者。

三、订阅者

   订阅者不止一个,它们都监听同一个topic。这里为了试验效果至少建两个订阅者,我这里只写一个,另一个大家照着写就行。

1.订阅者

package com.tgb.activemqTopic;

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;

/**
 * 消息的订阅者一
 * @author xx
 */
public class JMSConsumer1 {

	//默认连接用户名
	private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
	//默认连接密码
	private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
	//默认的连接地址
	private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL;
	
	public static void main(String[] args) {
		ConnectionFactory factory ; //连接工厂
		Connection connection = null ; //连接
		Session session ; //会话,接收或者发送消息的线程
		Destination destination; //消息的目的地
		MessageConsumer messageConsumer; //消息消费者
		//实例化连接工厂
		factory = new ActiveMQConnectionFactory(JMSConsumer1.USERNAME, JMSConsumer1.PASSWORD, JMSConsumer1.BROKEURL);
		//通过连接工厂获取connection
		try {
			connection = factory.createConnection();
			connection.start(); //启动连接
			//创建session
			session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
			//创建连接消息队列,消息到达的目的地
//			destination = session.createQueue("FirstQueue");
			destination = session.createTopic("topic1");
			//创建消费者
			messageConsumer = session.createConsumer(destination);
			//注册消息监听
			messageConsumer.setMessageListener(new Listener1());
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}


2.监听类

package com.tgb.activemqTopic;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

/**
 * 订阅者1的监听
 * 消息监听类
 * @author xx
 */
public class Listener1 implements MessageListener {

	@Override
	public void onMessage(Message message) {
		try {
			System.out.println("订阅者一收到的消息:" + ((TextMessage)message).getText());
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}

}

 四、测试

  像点对点的要先启动生产者,生产者要生产消息。而发布订阅模型,要先启动订阅者,订阅者先订阅topic,再发布消息。

1.启动订阅者,这里我启动两个,可以看到在topic中注册了两个消费者


2.启动发布者,如下

 发布者发布了10条数据,但是出队的有20条,因为有两个订阅者。

五、总结

    发布者向一个特定的消息主题发布消息,0或者多个订阅者可能接收到来自特定消息主题的消息感兴趣。其中发布者和订阅者不知道对方的存在。



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值