上篇博客介绍了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或者多个订阅者可能接收到来自特定消息主题的消息感兴趣。其中发布者和订阅者不知道对方的存在。