• JavaWeb之使用ActiveMQ实现JMS消息通信服务


    PTP(点对点的消息模型)

    在点对点模型中,相当于两个人打电话,两个人独享一条通信线路。一方发送消息,一方接收消息。

     

    在p2p的模型中,双方通过队列交流,一个队列只有一个生产者和一个消费者。

    1、建立项目 

    建立一个java项目,导入jar包,将apache-activemq-5.11.1-bin.zip解压缩后里面的activemq-all-5.11.1.jar包加入到classpath下面,这个包包含了所有JMS接口API的实现。

    点对点的消息模型,只需要一个消息生成者和消息消费者。

    • 编写生产者
    package com.tgb.activemq;
    
    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 liang
     *
     */
    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 SENDNUM = 10;
    
        public static void main(String[] args) {
            //连接工厂
            ConnectionFactory connectionFactory;
            //连接
            Connection connection = null;
            //会话 接受或者发送消息的线程
            Session session;
            //消息的目的地
            Destination destination;
            //消息生产者
            MessageProducer messageProducer;
            //实例化连接工厂
            connectionFactory = new ActiveMQConnectionFactory(JMSProducer.USERNAME, JMSProducer.PASSWORD, JMSProducer.BROKEURL);
    
            try {
                //通过连接工厂获取连接
                connection = connectionFactory.createConnection();
                //启动连接
                connection.start();
                //创建session
                session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
                //创建一个名称为HelloWorld的消息队列
                destination = session.createQueue("HelloWorld");
                //创建消息生产者
                messageProducer = session.createProducer(destination);
                //发送消息
                sendMessage(session, messageProducer);
    
                session.commit();
    
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                if(connection != null){
                    try {
                        connection.close();
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
        /**
         * 发送消息
         * @param session
         * @param messageProducer  消息生产者
         * @throws Exception
         */
        public static void sendMessage(Session session,MessageProducer messageProducer) throws Exception{
            for (int i = 0; i < JMSProducer.SENDNUM; i++) {
                //创建一条文本消息 
                TextMessage message = session.createTextMessage("ActiveMQ 发送消息" +i);
                System.out.println("发送消息:Activemq 发送消息" + i);
                //通过消息生产者发出消息 
                messageProducer.send(message);
            }
    
        }
    }
    View Code
    • 编写消费者
    package com.tgb.activemq;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.Destination;
    import javax.jms.JMSException;
    import javax.jms.MessageConsumer;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    
    import org.apache.activemq.ActiveMQConnection;
    import org.apache.activemq.ActiveMQConnectionFactory;
    /**
     * 消息的消费者(接受者)
     * @author liang
     *
     */
    public class JMSConsumer {
    
        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 connectionFactory;//连接工厂
            Connection connection = null;//连接
    
            Session session;//会话 接受或者发送消息的线程
            Destination destination;//消息的目的地
    
            MessageConsumer messageConsumer;//消息的消费者
    
            //实例化连接工厂
            connectionFactory = new ActiveMQConnectionFactory(JMSConsumer.USERNAME, JMSConsumer.PASSWORD, JMSConsumer.BROKEURL);
    
            try {
                //通过连接工厂获取连接
                connection = connectionFactory.createConnection();
                //启动连接
                connection.start();
                //创建session
                session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                //创建一个连接HelloWorld的消息队列
                destination = session.createQueue("HelloWorld");
                //创建消息消费者
                messageConsumer = session.createConsumer(destination);
    
                while (true) {
                    TextMessage textMessage = (TextMessage) messageConsumer.receive(100000);
                    if(textMessage != null){
                        System.out.println("收到的消息:" + textMessage.getText());
                    }else {
                        break;
                    }
                }
    
            } catch (JMSException e) {
                e.printStackTrace();
            }
    
        }
    }
    View Code 

    2、测试

    1)首先,启动ActiveMQ,在浏览器中输入:http://localhost:8161/admin/,然后开始执行程序。

    2)运行发送者JMSProducer,Eclipse控制台输出,如下图: 

    生产者生产10条消息。

    此时,查看ActiveMQ服务器,Queues内容如下:

    可以看到创建了一个名称为HelloWorld的消息队列,队列中有10条消息未被消费,我们也可以通过Browse查看是哪些消息,如下图:

    如果这些队列中的消息,被删除,消费者则无法消费。

    3)继续运行消费者JMSConsumer,eclipse控制台打印消息,如下:

    再查看ActiveMQ服务器,Queues内容如下:

    可以看到HelloWorld的消息队列发生变化,多一个消息者,队列中的10条消息被消费了,点击Browse查看,已经为空了。

    点击Active Consumers,我们可以看到这个消费者的详细信息:  

    3、总结

    点对点消息的传播,生产者向特定的消息队列传播消息,一个消费者从该队列读取消息。生产者不需要在接收者接收消息时处于运行,消费者也不需要生产者在发送消息时处于运行状态,队列相当于一个中间的仓库,生产者发送消息,立即返回状态发送成功。等消费者上线时 ,才接受消息。

    Pub/Sub(发布订阅模型

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

     

    1、建立项目 

    建立一个java项目,导入jar包。

    • 编写发布者(这里和点对点的不同就是不再是创建消息队列,而是创建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);
            }
        }
    }
    View Code
    • 编写订阅者1
    package com.tgb.activemqTopic;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.Destination;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageConsumer;
    import javax.jms.MessageListener;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import org.apache.activemq.ActiveMQConnectionFactory;
    
    public class JMSConsumer1 implements MessageListener {
    
        public void onMessage(Message message) {
            if (message instanceof TextMessage) {
                TextMessage txtMsg = (TextMessage) message;
    
                try {
                    System.out.println("订阅者一接收到了消息:" + txtMsg.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
    
            }
        }
    
        public void receive() {
            // 消费者的主要流程
            Connection connection = null;
    
            try {
                // 1.初始化connection工厂
                ConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
    
                // 2.创建Connection
                connection = connectionFactory.createConnection();
    
                // 3.打开连接
                connection.start();
    
                // 4.创建session
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
                // 5.创建消息目标
                Destination destination = session.createTopic("topic1");
    
                // 6.创建消费者
                MessageConsumer consumer = session.createConsumer(destination);
    
                // 7.配置监听
                consumer.setMessageListener(new JMSConsumer1());
    
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            new JMSConsumer1().receive();
        }
    
    }
    View Code
    • 编写订阅者2
    package com.tgb.activemqTopic;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.Destination;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageConsumer;
    import javax.jms.MessageListener;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import org.apache.activemq.ActiveMQConnectionFactory;
    
    public class JMSConsumer2 implements MessageListener {
    
        public void onMessage(Message message) {
            if (message instanceof TextMessage) {
                TextMessage txtMsg = (TextMessage) message;
    
                try {
                    System.out.println("订阅者二接收到了消息:" + txtMsg.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
    
            }
        }
    
        public void receive() {
            // 消费者的主要流程
            Connection connection = null;
    
            try {
                // 1.初始化connection工厂
                ConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
    
                // 2.创建Connection
                connection = connectionFactory.createConnection();
    
                // 3.打开连接
                connection.start();
    
                // 4.创建session
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
                // 5.创建消息目标
                Destination destination = session.createTopic("topic1");
    
                // 6.创建消费者
                MessageConsumer consumer = session.createConsumer(destination);
    
                // 7.配置监听
                consumer.setMessageListener(new JMSConsumer1());
    
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            new JMSConsumer2().receive();
        }
    
    }
    View Code

    2、测试

    1)首先,启动ActiveMQ,在浏览器中输入:http://localhost:8161/admin/,然后开始执行程序。

    2)发布订阅模型,要先启动订阅者,订阅者先订阅topic,再发布消息。

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

    3)启动发布者,如下:

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

    3、总结

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

    配置消息是否持久化

    1、建立项目 

    //配置消息是否持久化,DeliverMode有2种方式
    /*
    * 1 不持久化:服务器重启之后,消息销毁
    * 2 持久化:服务器重启之后,该消息仍存在
    */
    messageProducer.setDeliveryMode(2);

    • 编写发布者
    package com.tgb.activemqTopic;
    
    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(true, Session.AUTO_ACKNOWLEDGE);        
                //创建主题
                destination = session.createTopic("topic1");
                //创建消息发布者
                messageProducer = session.createProducer(destination);
                
                //配置消息是否持久化,DeliverMode有2种方式
                /*
                 * 1 不持久化:服务器重启之后,消息销毁 
                 * 2 持久化:服务器重启之后,该消息仍存在
                 */        
                messageProducer.setDeliveryMode(2);
                
                //发送消息
                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);
            }
        }
    }
    View Code

    2、测试

    1)首先,启动ActiveMQ,在浏览器中输入:http://localhost:8161/admin/,然后开始执行程序。

    2)先2个启动订阅者,再启动发布者,如下:

  • 相关阅读:
    git撤销修改
    python参数组合
    java打包jar后,使之一直在linux上运行,不随终端退出而关闭
    输入流加载资源文件的3种方式
    ActiveMQ集群下的消息回流功能
    activemq在一台服务器上启动多个Broker
    JAVA多线程下载
    829. 连续整数求和-leetcode
    mysql笔记-索引
    redis源码学习-skiplist
  • 原文地址:https://www.cnblogs.com/YSPXIZHEN/p/6890588.html
Copyright © 2020-2023  润新知