一、ActiveMQ简介、安装、PTP模式和Topic模式

一、JMS简介

  • JMS全称 Java Message Service(Java消息服务),是java的一套API标准,是企业消息产品(有时也被称为消息中间件产品),最初的目的是为了使程序能够访问MOM系统(Message Oriented Middleware 面向消息的中间件 ),利用高效可靠的消息传递机制进行平台无关的数据交流,还可以在分布式系统中发送消息,进行异步通信。JMS是一个于平台无关的API,大多数的MOM提供商都支持JMS。常见的MOM系统:RocketMQ、RabbitMQ、ActiveMQ等,基于JMS实现的MOM,又称为JMS Provider。
  • 消息是JMS中提供的一种类型对象,可以在计算机之间进行传输的数据单位,消息类型:简单文本(TextMessage)、可序列化的对象 (ObjectMessage)、属性集合 (MapMessage)、字节流 (BytesMessage)、原始值流 (StreamMessage),还有无有效负载的消息 (Message)。
  • 消息被发送到消息队列中,消息队列是消息在传输过程中消息的存放容器,进行异步处理,减少响应时间和解耦。消息队列提供路由保证消息的传递,如果消息没有被消费者消费(被接收),消息队列就会保留消息,直至消息被接收。

二、ActiveMQ简介

ActiveMQ是由·Apache·出品,完全支持JMS1.1JavaEE1.4规范的JMS Provider 实现,是MOM(面向消息的中间件)的中间件。

  • 1、支持的编程语言:C、C++、C#、Delphi、Erlang、Adobe Flash、Haskell、Java、JavaScript、Perl、PHP、Pike、Python和Ruby;
  • 2、支持的协议:OpenWire、REST、STOMP、WS-Notification、MQTT、XMPP以及AMQP;
  • 3、支持多种传送协议:in-VM、TCP、SSL、NIO、UDP、IGroups、JXTA。
  • 4、对Spring支持,ActiveMQ可以跟Spring整合;
  • 5、支持集群,客户端-服务器,点对点;
  • 6、支持Ajax。

三、Linux上安装ActiveMQ

首先到官网http://activemq.apache.org/components/classic/download/上进行下载
在这里插入图片描述

  • 1、将下载好的压缩文件上传到Linux上(我上传的目录是/opt下)
  • 2、使用解压命令 tar -zxvf apache-activemq-5.15.9-bin.tar.gz
  • 3、检查是否安装JDK,如果没有安装JDK,无法启动ActiveMQ。
  • 4、解压完成后进入bin目录 cd apache-activemq-5.15.9/bin ,使用 ./activemq start 命令启动activemq
  • 5、启动完成后再浏览器中输入http://你的Linux ip:8161

在这里插入图片描述
然后点击红框中的内容,输入用户名和密码(都是 admin)

四、PTP处理模式(Queue)

消息生产者将消息发送到queue(消息队列)中,消息消费者然后从queue中获取消息并消费。消息被消费后,queue中不再有消息,所以消息消费者是不可能去消费已经被消费掉的消息。Queue支持存在多个消息消费者,但是对一个消息而言,只能有一个消息消费者去消费它,其它消息消费者则不能去消费。当消息消费者不存在时,消息就会一直存在queue中,直到有消息消费者去消费消息。

1、主动模式

创建一个JavaSE工程,引入ActiveMQ的jar包。
在这里插入图片描述

1)消息生产者

/**
 * 消息生产者
 */
public class Producer {
    /**
     * 发送消息到ActiveMQ中,使用的接口全都在javax.jms包下
     */
    public void sendTextMessage(String datas) {
        // 连接工厂
        ConnectionFactory connectionFactory = null;
        // 连接
        Connection connection = null;
        // 目的地
        Destination destination = null;
        // 会话
        Session session = null;
        // 消息生产者
        MessageProducer messageProducer = null;
        // 消息对象
        Message message = null;
        try {
            /**
             * 创建连接工厂对象
             * 无参构造:有默认的连接地址(本地连接localhost)
             * 单个参数构造:无认证模式(没有用户进行认证),指定连接地址
             * 三个参数构造:有认证、指定地址(默认端口是61616,在conf/activemq.xml文件中查看)
             *
             *
             * 目前首先使用ActiveMQ提供的默认用户
             *
             */
            connectionFactory = new ActiveMQConnectionFactory(
                    ActiveMQConnectionFactory.DEFAULT_USER,
                    ActiveMQConnectionFactory.DEFAULT_PASSWORD,
                    "tcp://xxx:61616");
            /**
             * 通过工厂对象创建连接
             * 创建连接方法有两个重载,有参数和无参数
             * createConnection(String username, String password),参数是用户名和密码
             * 前面创建连接工厂的时候已经传递,这里就不需要了。
             */
            connection = connectionFactory.createConnection();
            /**
             * 消息生产者不是必须启动连接(建议启动),消息消费者必须启动连接
             */
            connection.start();
            /**
             * 通过连接对象创建会话
             *
             * createSession方法有连个参数,
             * 第一个参数:是否支持事务(transacted),true支持、false不支持(常用)
             * 第二个参数:acknowledge(如何处理消息,消息处理后就从消息队列中移除),有三个可以值,如下:
             * 1、AUTO_ACKNOWLEDGE:自动确认消息(消息消费者处理消息后自动确认,常用)
             * 2、CLIENT_ACKNOWLEDGE:客户端手动确认(消息消费者处理消息后手动确认)
             * 3、DUPS_OK_ACKNOWLEDGE:允许副本确认,消息可以进行重复确认,但是其他的消息消费者不能再消费这个消息
             */
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            // 通过会话对象创建目的地,参数是目的地名称,是目的地唯一标识
            destination = session.createQueue("ptp auto mq");
            /**
             *  通过会话对象创建消息生产者Producer,
             *  创建Producer的时候可以不指定destination,发送消息的时候在指定
             */
            messageProducer = session.createProducer(null);
            // 通过会话对象创建文本对象
            message = session.createTextMessage(datas);
            // 使用Producer对象,发送消息到ActiveMQ中的目的地,如果消息发送失败就抛异常
            messageProducer.send(destination, message);
            System.out.println("消息发送成功!");
        } catch (JMSException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (messageProducer != null) {
                try {
                    messageProducer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (session != null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        Producer producer = new Producer();
        producer.sendTextMessage("这是第一个ActiveMQ示例");
    }
}

2)、消息消费者

/**
 * 消息消费者
 */
public class Consumer {
    public void receiveTextMessage() {
        // 连接工厂
        ConnectionFactory connectionFactory = null;
        // 连接
        Connection connection = null;
        // 会话
        Session session = null;
        // 目的地
        Destination destination = null;
        // 消息消费者
        MessageConsumer consumer = null;
        // 消息
        Message message = null;
        try {
            // 创建连接工厂对象
            connectionFactory = new ActiveMQConnectionFactory(
                    ActiveMQConnectionFactory.DEFAULT_USER,
                    ActiveMQConnectionFactory.DEFAULT_PASSWORD,
                    "tcp://192.168.48.129:61616"
            );
            // 通过连接工厂对象创建连接对象
            connection = connectionFactory.createConnection();
            // 消息消费者必须启动连接,否则无法处理消息
            connection.start();
            // 通过连接对象创建会话
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            // 通过会话对象创建目的地,参数是目的地名称,是目的地唯一标识
            destination = session.createQueue("ptp auto mq");
            //通过会话对象创建消息消费者,指定目的地
            consumer = session.createConsumer(destination);
            // 通过消息消费者对象获取消息队列中的消息
            message = consumer.receive();
            getMessageType(message);
        } catch (JMSException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (consumer != null) {
                try {
                    consumer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (session != null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // 判断消息类型
    private void getMessageType(Message message) {
        try {
            if (message instanceof TextMessage) {
                // 强转
                TextMessage textMessage = (TextMessage) message;
                System.out.println(textMessage.getText());
            } else if (message instanceof ObjectMessage) {
                ObjectMessage objectMessage = (ObjectMessage) message;
            } else if (message instanceof MapMessage) {
                MapMessage mapMessage = (MapMessage) message;
            } else if (message instanceof BytesMessage) {
                BytesMessage bytesMessage = (BytesMessage) message;
            } else if (message instanceof StreamMessage) {
                StreamMessage streamMessage = (StreamMessage) message;
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        Consumer consumer = new Consumer();
        consumer.receiveTextMessage();
    }
}

2、监听器消费模式

1)消息生产者

try {
    // 创建连接工厂对象
    connectionFactory = new ActiveMQConnectionFactory(
          ActiveMQConnectionFactory.DEFAULT_USER,
          ActiveMQConnectionFactory.DEFAULT_PASSWORD,
          "tcp://xxx:61616"
     );
     // 通过连接工厂对象创建连接对象
     connection = connectionFactory.createConnection();
     // 开启连接
     connection.start();
     // 通过连接对象创建会话
     // 客户端确认
     session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
     // 通过会话对象创建目的地
     destination = session.createQueue("test-listener");
     /**
      *  通过会话对象创建消息生产者Producer,
      *  创建Producer的时候可以不指定destination,发送消息的时候在指定
      */
      producer = session.createProducer(destination);
      // 创建消息对象并发送消息
      for (int i = 0; i < 100; i++) {
          message = session.createTextMessage("消息" + i);
          producer.send(message);
       }
} catch (JMSException e) {
   e.printStackTrace();
} 

2)消息消费者


        try {
            // 创建连接工厂对象
            connectionFactory = new ActiveMQConnectionFactory(
                    ActiveMQConnectionFactory.DEFAULT_USER,
                    ActiveMQConnectionFactory.DEFAULT_PASSWORD,
                    "tcp://xxx:61616"
            );
            // 通过连接工厂对象创建连接
            connection = connectionFactory.createConnection();
            // 开启连接
            connection.start();
            // 通过连接对象创建会话
            session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
            // 通过会话对象创建目的地
            destination = session.createQueue("test-listener");
            // 通过会话对象创建消费者
            consumer = session.createConsumer(destination);
            // 注册监听器
            consumer.setMessageListener(new MessageListener() {
                /**
                 * 监听器一旦注册,永久有效(consumer线程不关闭),
                 * 处理消息方式:只要有未处理的消息,自动调用onMessage方法处理消息,
                 * 监听器可以注册若干个,注册多个监听器相当于集群,
                 * ActiveMQ自动循环调用多个监听器来处理队列中的消息,实现并行处理
                 *
                 * @param message 未处理的消息
                 */
                @Override
                public void onMessage(Message message) {
                     // 使用客户端确认,就要调用acknowledge方法,acknowledge方法就是确认方法,代表消息消费者消费了消息,确认后将对应的消息从消息列表中删除                              
                    message.acknowledge();                                                                                                                                                                                 
                    handleMessage(message);
                }
            });
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

五、Publish/Subscribe模式(Topic)

消息生产者(发布)将消息发布到topic中,同时多个消息消费者(订阅)消费该消息。
Publish/Subscribe模式和PTP模式不同,发布到topic的消息会被所有的消息消费者(订阅)消费。消息生产者发布消息,不管是否有消息消费者(订阅)消费消息,消息都不会保存。

消息生产者

        try {
            // 创建连接工厂
            connectionFactory = new ActiveMQConnectionFactory(
                    ActiveMQConnectionFactory.DEFAULT_USER,
                    ActiveMQConnectionFactory.DEFAULT_PASSWORD,
                    "tcp://xxx:61616"
            );
            // 通过连接工厂对象创建连接
            connection = connectionFactory.createConnection();
            // 开启连接(消息生产者建议开启)
            connection.start();
            //通过连接对象创建会话
            // 不开启事务,客户端确认
            session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
            // 通过会话对象创建Topic
            destination = session.createTopic("test-topic");
            // 通过会话对象创建消息生产者
            producer = session.createProducer(destination);
            message = session.createTextMessage("这是发布的消息3");
            producer.send(message);
            System.out.println("发布成功!");
        } catch (JMSException e) {
            e.printStackTrace();
        } 

消息消费者

        try {
            // 创建连接工厂对象
            connectionFactory = new ActiveMQConnectionFactory(
                   ActiveMQConnectionFactory.DEFAULT_USER,
                    ActiveMQConnectionFactory.DEFAULT_PASSWORD,
                    "tcp://xxx:61616"
            );
            // 通过连接工厂对象创建连接
            connection = connectionFactory.createConnection();
            // 开启连接(消息消费者必须开启)
            connection.start();
            // 通过连接对象创建会话
            // 不开启事务,客户端确认
            session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
            // 通过会话对象创建Topic
            destination = session.createTopic("test-topic");
            // 通过会话对象创建消息消费者
            consumer = session.createConsumer(destination);
            // 接收消息
            message = consumer.receive();
            handleMessage(message);
            // 使用客户端确认,就要调用acknowledge方法,acknowledge方法就是确认方法,代表消息消费者消费了消息,确认后将对应的消息从消息列表中删除                              
            message.acknowledge();
        } catch (JMSException e) {
            e.printStackTrace();
        }

公众号二维码
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值