消息中间件之ActiveMQ PTP和PUB/SUB模式实例(三)
来源:互联网 发布:淘宝系统怎么判定假货 编辑:程序博客网 时间:2024/05/17 14:24
1 前言
在JMS那篇文章中我有提过消息通信模式,主要的模式有两种点对点(Point-to-Point)、发布-订阅(Publish/Subscribe),在那篇文章中我只是描述了一些理论性的东西,并没有实际的案例,这篇文章我将用案例来讨论这两个模式。
2 点对点(P2P)
p2p的过程则理解起来比较简单。它好比是两个人打电话,这两个人是独享这一条通信链路的。一方发送消息,另外一方接收,就这么简单。它的通信场景如下图所示:
2.1 案例
生产端
class Publisher { private ActiveMQConnectionFactory factory; private Connection connection; private Session session; private MessageProducer producer; private Destination destination; public Publisher() throws JMSException { //建立ConnectionFactory工厂对象,需要填入用户名、密码、以及要连接的地址,均使用默认即可,默认端囗为“tcp://localhost:61616” factory = new ActiveMQConnectionFactory( "hfbin", "hfbin", "tcp://localhost:61616"); //2通过ConnectionFactory工厂对象我们创建一个Connection连接,并且调用Connection的start方法开启连接,Connection默认是关闭的。 connection = factory.createConnection(); connection.start(); //3 过Connection对象创建Session会话(上下文环境对象),用于接收消息,参数配置1为是否启用是事务,参数配置2为签收模式,一般我们设置自动签收。 session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); ////4通过Session创建Destination对象,指的是一个客户端用来指定生产消息目标和消费消息来源的对象,在PTP模式中,Destination被称作Queue即队列:在Pub/Sub模式,Destination被称作Topic及主题。在程序中可以使用多个Queue和Topic。 destination = session.createQueue("queue2"); //5我们需要通过Session对象创建消息的发送和接收对象生产者 MessageProducer。 producer = session.createProducer(destination); } //6 该方法实现数据发送 public void sendMessage() throws JMSException { for(int i = 0; i < 5; i++) { TextMessage message = session.createTextMessage("I Tell You >> "+i); System.out.println("生产数据: " + "I Tell You >> "+i); producer.send(destination, message); } connection.close(); } public static void main(String[] args) throws JMSException { Publisher publisher = new Publisher(); publisher.sendMessage(); }}
这里我使用了构造函数初始化所有的资源,在这我不做过多说明,这里代码我上一篇文章都有详细的说明。
消费端
public class Consumer { private ActiveMQConnectionFactory factory; private Connection connection; private Session session; private MessageConsumer consumer; private Destination destination; public Consumer() throws JMSException { factory = new ActiveMQConnectionFactory( "hfbin", "hfbin", "tcp://localhost:61616" ); connection = factory.createConnection(); connection.start(); session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); destination = session.createQueue("queue2"); //通过Session对象创建消息的发送和接收对象消费者 MessageConsumer。 consumer = session.createConsumer(destination); } //获取数据 public void getMessage() throws JMSException { //使用监听方式获取数据 ,在这我定义了内部类Listener需要实现MessageListener接口然后实现里面的方法。 consumer.setMessageListener(new Listener()); } //内部类 实现了MessageListener接口,里面的onMessage方法就是在接收到消息之后会被调用的方法 class Listener implements MessageListener{ @Override public void onMessage(Message message) { if (message instanceof TextMessage){ try { System.out.println(((TextMessage) message).getText()); } catch (JMSException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws JMSException { Consumer consumer = new Consumer(); consumer.getMessage(); }}
接收和处理消息的方法有两种,分为同步和异步的,一般同步的方式我们是通过MessageConsumer.receive()方法来处理接收到的消息。而异步的方法则是通过注册一个MessageListener的方法,使用MessageConsumer.setMessageListener()。这里我采用异步的方式实现。
这里我就不给出结果了,需要的可以自己到我的GitHub上下载代码,自己测试。
源代码:https://github.com/hfbin/Thread_Socket/tree/master/ActiveMQ/PTP
3 发布/订阅(Pub/Sub)
发布订阅模式有点类似于我们日常生活中订阅报纸。每年到年尾的时候,邮局就会发一本报纸集合让我们来选择订阅哪一个。在这个表里头列了所有出版发行的报纸,那么对于我们每一个订阅者来说,我们可以选择一份或者多份报纸。比如北京日报、潇湘晨报等。那么这些个我们订阅的报纸,就相当于发布订阅模式里的topic。有很多个人订阅报纸,也有人可能和我订阅了相同的报纸。那么,在这里,相当于我们在同一个topic里注册了。对于一份报纸发行方来说,它和所有的订阅者就构成了一个1对多的关系。这种关系如下图所示:
3.1 案例
其实这个案例跟PTP差不多就改一下创建类型而已,将session.createQueue()
改成session.createTopic()
而已,然后多几个消费端的类。
生产端
class Publisher { private ActiveMQConnectionFactory factory; private Connection connection; private Session session; private MessageProducer producer; private Destination destination; public Publisher() throws JMSException { //建立ConnectionFactory工厂对象,需要填入用户名、密码、以及要连接的地址,均使用默认即可,默认端囗为“tcp://localhost:61616” factory = new ActiveMQConnectionFactory( "hfbin", "hfbin", "tcp://localhost:61616"); //2通过ConnectionFactory工厂对象我们创建一个Connection连接,并且调用Connection的start方法开启连接,Connection默认是关闭的。 connection = factory.createConnection(); connection.start(); //3 过Connection对象创建Session会话(上下文环境对象),用于接收消息,参数配置1为是否启用是事务,参数配置2为签收模式,一般我们设置自动签收。 session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); ////4通过Session创建Destination对象,指的是一个客户端用来指定生产消息目标和消费消息来源的对象,在PTP模式中,Destination被称作Queue即队列:在Pub/Sub模式,Destination被称作Topic及主题。在程序中可以使用多个Queue和Topic。 destination = session.createTopic("Topic"); //5我们需要通过Session对象创建消息的发送和接收对象生产者 MessageProducer。 producer = session.createProducer(destination); } //6 该方法实现数据发送 public void sendMessage() throws JMSException { for(int i = 0; i < 5; i++) { TextMessage message = session.createTextMessage("I Tell You >> "+i); System.out.println("生产数据: " + "I Tell You >> "+i); producer.send(destination, message); } connection.close(); } public static void main(String[] args) throws JMSException { Publisher publisher = new Publisher(); publisher.sendMessage(); }}
每一个消费端的代码都是一模一样的。
消费端1
public class Consumer1 { private ActiveMQConnectionFactory factory; private Connection connection; private Session session; private MessageConsumer consumer; private Destination destination; public Consumer1() throws JMSException { factory = new ActiveMQConnectionFactory( "hfbin", "hfbin", "tcp://localhost:61616" ); connection = factory.createConnection(); connection.start(); session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); destination = session.createTopic("Topic"); consumer = session.createConsumer(destination); } public void getMessage() throws JMSException { consumer.setMessageListener(new Listener()); } class Listener implements MessageListener{ @Override public void onMessage(Message message) { if (message instanceof TextMessage){ try { System.out.println(((TextMessage) message).getText()); } catch (JMSException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws JMSException { Consumer1 consumer1 = new Consumer1(); consumer1.getMessage(); }}
消费端2
public class Consumer2 { private ActiveMQConnectionFactory factory; private Connection connection; private Session session; private MessageConsumer consumer; private Destination destination; public Consumer2() throws JMSException { factory = new ActiveMQConnectionFactory( "hfbin", "hfbin", "tcp://localhost:61616" ); connection = factory.createConnection(); connection.start(); session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); destination = session.createTopic("Topic"); consumer = session.createConsumer(destination); } public void getMessage() throws JMSException { consumer.setMessageListener(new Listener()); } class Listener implements MessageListener{ @Override public void onMessage(Message message) { if (message instanceof TextMessage){ try { System.out.println(((TextMessage) message).getText()); } catch (JMSException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws JMSException { Consumer2 Consumer2 = new Consumer2(); Consumer2.getMessage(); }}
这里启动时候建议先启动消费端,然后再进行生产端的启动,等生产端运行完毕后我们查看消费端1、消费端2都打印了生产端发送的数据。
源代码:https://github.com/hfbin/Thread_Socket/tree/master/ActiveMQ/PubSub
现在如果我们比较一下pub-sub和p2p模式的具体实现步骤的话,我们会发现他们基本的处理流程都是类似的,除了在pub-sub中要通过createTopic来设置topic,而在p2p中要通过createQueue来创建通信队列。
- 消息中间件之ActiveMQ PTP和PUB/SUB模式实例(三)
- ActiveMQ两种模式PTP和PUB/SUB
- activeMQ之点对点(PTP),监听器模式
- JMS开发(二):深入PTP,Pub-Sub两种模式
- springmvc+spring+maven+ActiveMq之:PuB/Sub模式
- ActiveMQ消息中间件之队列模式和主题模式详解
- activeMQ之点对点(PTP),主动接受消息
- ActiveMQ点对点模式(PTP)
- ZeroMQ之PUB/SUB模式
- 【EJB四】JMS消息服务之P2P和Pub/Sub
- Spring和ActiveMQ集成实现队列消息以及PUB/SUB模型
- Spring和ActiveMQ集成实现队列消息以及PUB/SUB模型
- Spring和ActiveMQ集成实现队列消息以及PUB/SUB模型
- spring boot整合activeMQ,实现ptp和topic两者消息模式
- 消息中间件-activemq消息机制和持久化介绍(三)
- ActiveMQ demos-Pub/Sub domain
- ActiveMq--Pub/Sub的使用
- JMS实战之三 ------如何安装消息中间件ActiveMQ
- Codeforces Round #445 D. Symmetric Projections
- linux硬链接和软链接的区别
- org.apache.catalina.loder.WebappClassLoaderBase.class
- 浅析BFS——HDU 1548 A Strange lift
- Linux 字符设备驱动开发基础(一)—— 编写简单 LED 设备驱动
- 消息中间件之ActiveMQ PTP和PUB/SUB模式实例(三)
- ninja1.72
- Win8使用VirtualBox安装CentOS 6.4教程
- 解决问题:编译Latex遇到File ended while scanning use of \@writefile
- HTTP
- MD5、RSA、Base64、ASE加密算法
- PAT (Basic Level) Practise (中文)1035. 插入与归并(25)
- 【098】Java利用对象池配合synchronized同步块实现较高效率的线程同步
- hibernate系列十:多对多关联配置及案例(二)