activemq订阅模式--java教程

activemq有订阅模式,该模式是直接群发,消息不保存。

生产者:

先写个生成者的demo

package org.example.activemqtest;


import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.util.Scanner;

public class Provider {
    public static String username = "admin";
    public static String password = "admin";
    public static String url ="tcp://localhost:61616";//采用openwire

    public static String name="test_topic_1";

    private ConnectionFactory connectionFactory;

    private Connection connection;

    private Session session;
    {

        try {
            /**
             * 1.创建连接工厂
             * 创建工厂,构造方法有三个参数:分别是用户名、密码、连接地址
             * 无参构造:有默认的连接地址,localhost
             * 一个参数:无验证模式,无用户的认证
             * 三个参数:有认证和连接地址
             */
            connectionFactory = new ActiveMQConnectionFactory(username,password,url);
            connection = connectionFactory.createConnection();
            /**
             * 3.启动连接
             * 生产者可以不启动,因为在发送消息的时候回进行检查
             * 如果未启动连接,会自动启动
             * 如果有特殊配置,需要配置完成后再启动连接
             */
            connection.start();
            /**
             * 4.用连接创建会话
             * 有两个参数:是否需要事务、消息确认机制
             * 如果支持事务,对于生产者来说第二个参数就无效了,建议传入Session.SESSION_TRANSACTED
             * 如果不支持事务,第二个参数必须传递且有效
             *
             * AUTO_ACKNOWLEDGE:自动确认,消息处理后自动确认(商业开发不推荐)
             * CLIENT_ACKNOWLEDGE:客户端手动确认,消费者处理后必须手动确认
             * DUPS_OK_ACKNOWLEDGE:有副本的客户端手动确认,消息可以多次处理(不建议)
             */
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            System.out.println("clientID = " + connection.getClientID());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
    private void send(String text) throws JMSException {
        Destination queue = session.createTopic(name);
        MessageProducer producer = session.createProducer(queue);
        producer.send(session.createTextMessage(text));

    }

    public static void main(String[] args) throws Exception {
       Provider provider = new Provider();


        Scanner scan = new Scanner(System.in);

        // 判断是否还有输入
        while (scan.hasNextLine()) {
            String str2 = scan.nextLine();
            System.out.println("发送的数据为:" + str2);
            provider.send(str2);
        }
        scan.close();
    }
}

可以看到,代码实际上就是new Provicder().send(text)

普通代码块里创建了连接,send方法往test_topic_1里发送数据.然后发送者就结束了,就不再管了.

至于Scanner是为了屏幕输入然后发送

我们启动这个main方法,发送一条数据

1111
发送的数据为:1111

然后观察active后台控制台里:

 可以发现test_topic_1这个队列里已经有了一条数据。

 

消费者:

package org.example.activemqtest;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.time.LocalDateTime;

public class Receiver {
    public static final String username ="admin";
    private static final String password ="admin";

    public static final String url ="tcp://localhost:61616";
    public static String name="test_topic_1";
    Connection connection;
    Session session;

    {

        try {
            /**
             * 1.创建连接工厂
             * 创建工厂,构造方法有三个参数:分别是用户名、密码、连接地址
             * 无参构造:有默认的连接地址,localhost
             * 一个参数:无验证模式,无用户的认证
             * 三个参数:有认证和连接地址
             */
            ConnectionFactory factory = new ActiveMQConnectionFactory(username,password,url);
            connection = factory.createConnection();
            /**
             * 3.启动连接
             * 生产者可以不启动,因为在发送消息的时候回进行检查
             * 如果未启动连接,会自动启动
             * 如果有特殊配置,需要配置完成后再启动连接
             */
            connection.start();
            /**
             * 4.用连接创建会话
             * 有两个参数:是否需要事务、消息确认机制
             * 如果支持事务,对于生产者来说第二个参数就无效了,建议传入Session.SESSION_TRANSACTED
             * 如果不支持事务,第二个参数必须传递且有效
             *
             * AUTO_ACKNOWLEDGE:自动确认,消息处理后自动确认(商业开发不推荐)
             * CLIENT_ACKNOWLEDGE:客户端手动确认,消费者处理后必须手动确认
             * DUPS_OK_ACKNOWLEDGE:有副本的客户端手动确认,消息可以多次处理(不建议)
             */
            session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

    public void receive() throws JMSException {
        Destination queue = session.createTopic(name);

        MessageConsumer consumer = session.createConsumer(queue);
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                try{
                    TextMessage m = (TextMessage)message;
                    String text = m.getText();
                    System.out.println(LocalDateTime.now() +" : " +text);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

    }

    public static void main(String[] args) throws JMSException {
        new Receiver().receive();
    }

}

可以看到,在连接到消息中间件后,客户端就加了一个而监听器而已,监听器里打印了发来的数据

然后我们运行,发现没有打印任何数据,没有获得刚刚发的1111,因为订阅模式消息不保存,直接抛弃了。如果当时没有订阅就接不到。

我们再看到控制台:

发现多了一个接收者,但是消息订阅数还是0,并没有增加。

 

进一步测试

我们再发一条222消息进行测试,发现消费者接到了消息。控制台如下:

发现生产的消息多了一条,消费总数也多了一条。

由于订阅模式特征就是群发,那么再启动一个消费者,然后再发一条333,发现两个消费者都接到了。控制台如下:

 

发现消费者多了一个,消息多了一个,但是消费总数居然多了两个,原因在于消费总数就是消费总数,刚刚两个消费者消费了所以+2,如果是3个消费者,那么要加3

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