消息中间件之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来创建通信队列。

阅读全文
0 0
原创粉丝点击