ActiveMQ的安装与简单使用


这学期在软件平台与中间件这门课上学习了消息中间件的内容,这里我以ActiveMQ为例给大家讲解一下ActiveMQ的安装与简单使用,若有不对的地方欢迎指正!

一、ActiveMQ的安装与配置

1、下载安装包
官网下载地址: http://activemq.apache.org/components/classic/download/
根据自己的电脑的系统下载对应的版本.(此处我是Windows版本)
在这里插入图片描述
2、解压
到下载压缩包的目录里,解压压缩包
在这里插入图片描述3、启动
进入相对目录: \apache-activemq-5.16.2\bin\win64
点击activemq.bat
在这里插入图片描述
成功启动ActiveMQ
在这里插入图片描述4、访问
游览器输入地址: http://127.0.0.1:8161/admin/ 访问
账号和密码默认为: admin/admin
在这里插入图片描述

二、ActiveMQ的简介

2.1 ActiveMQ是由Apache出品的一款开源消息中间件,旨在为应用程序提供高效、可扩展、稳定、安全的企业级消息通信。它的设计目标是提供标准的、面向消息的、多语言的应用集成消息通信中间件。ActiveMQ实现了JMS 1.1并提供了很多附加的特性,比如JMX管理、主从管理、消息组通信、消息优先级、延迟接收消息、虚拟接收者、消息持久化、消息队列监控等。
在这里插入图片描述2.2 ActiveMQ应用场景
(1)异步处理
串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。
在这里插入图片描述并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。
在这里插入图片描述(2)应用解耦

如下图,应用消息队列后,库存系统不能正常使用,也不直接影响订单系统。

  • 订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功
  • 库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作(ps:)
    在这里插入图片描述对比下图:

传统模式的缺点

  • 假如库存系统无法访问,则订单减库存将失败,从而导致订单失败;
  • 订单系统与库存系统耦合;
    在这里插入图片描述(3)流量削峰
     如下图,相信大家在网购时都有体验,一个典型的应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。这样,用户的请求,服务器接收后,首先写入消息队列。
    在这里插入图片描述这样做有如下好处:
    • 可以控制活动的人数:假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面
    • 可以缓解短时间内高流量压垮应用:秒杀业务根据消息队列中的请求信息,再做后续处理

其他的场景还有:日志处理,消息通讯等。

三、ActiveMQ实例

在这里插入图片描述

3.1 Queue模式

消息生产者
ProduceQueue.java

package com.fightwk.active;

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;

public class ProduceQueue {
    /**
     * 发送消息到ActiveMQ中,具体的消息内容为参数信息
     * 开发JMS相关代码中,使用的接口类型都是javax.jms包下的类型
     */
    public void sendTextMessage(String datas){
        //连接工厂
        ConnectionFactory factory = null;
        //连接
        Connection connection = null;
        //目的地
        Destination destination = null;
        //会话
        Session session = null;
        //消息发送者
        MessageProducer producer = null;
        //消息对象
        Message message = null;
        try{
            //创建连接工厂,连接ActiveMQ服务的连接工厂
            //创建工厂,构造方法有三个参数,分别是用户名,密码,连接地址
            //无参构造,有默认的连接地址。本地连接
            //单参数构造,五无验证模式,没有用户的认证
            //三参数构造,有认证+指定地址。默认端口是61616.从ActiveMQ的conf/activemq.xml配置文件中查看
            factory = new ActiveMQConnectionFactory("admin","admin","tcp://localhost:61616");
            //通过工厂,创建连接对象
            //创建连接的方法有重载,其中有createConnection(String username,String password)
            //可以再创建连接工厂时,只传递连接地址,不传递用户信息
            connection = factory.createConnection();
            //建议启动连接,消息的发送者不是必须启动连接。消息的消费者必须启动连接
            //producer再发送消息的时候,会检查是否启动了连接,如果未启动,自动启动
            //如果有特殊的配置,建议配置完毕后再启动连接
            connection.start();
            //通过连接对象,创建会话对象
            /*创建会话的时候,必须传递两个参数,分别代表的是否支持事务和如何确认消息处理
             * transacted:是否支持事务,数据类型是boolean.true-支持  false-不支持
             * 		true:支持事务,第二个参数对producer来说默认是无效。建议传递的数据是Session.SESSION_TRANSACTED
             * 		false:不支持事务,常用参数。第二个参数必须传递,且必须有效
             * acknowledgeMode:如何确认消息的处理。使用确认机制实现的
             * 		AUTO_ACKNOWLEDGE:自动确认消息。消息的消费者处理消息后,自动确认。常用。商业开发不推荐
             * 		CLIENT_ACKNOWLEDGE:客户端手动确认。消息的消费者处理后,必须手工确认
             * 		DUPS_OK_ACKNOWLEDGE:有副本的客户端手动确认
             * 				一个消息可以多次处理
             * 				可以降低Session的消耗,再可以容忍重复消息时使用(不推荐使用)
             */
            session = connection.createSession(Boolean.FALSE, Session.CLIENT_ACKNOWLEDGE);
            //创建目的地。参数是目的地名称。是目的地的唯一标记
            destination = session.createQueue("fightwk");
            //通过会话对象,创建消息的发送者producer
            //创建的消息发送者,发送的消息一定到指定的目的地中
            //创建producer的时候,可以不提供目的地。在发送消息的时候制定目的地
            producer = session.createProducer(destination);
            //创建文本消息对象,作为具体数据内容的载体
            message = session.createTextMessage(datas);
            //使用producer,发送消息到ActiveMQ中的目的地。如果消息发送失败。抛出异常
            producer.send(message);

            System.out.println("消息已经发送成功....");
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(producer != null){//回收消息发送者
                try {
                    producer.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){
        ProduceQueue producer = new ProduceQueue();
        producer.sendTextMessage("我是一个测试的ActiveMQ...");
    }
}

消息消费者
ConsumerQueue.java

package com.fightwk.active;

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;

public class ConsumerQueue {
    public String receiveTextMessage(){
        String resultCode = "";
        ConnectionFactory factory = null;
        Connection connection = null;
        Session session = null;
        Destination destination = null;
        //消息的消费者,用于接收消息的对象
        MessageConsumer consumer = null;
        TextMessage message = null;

        try{
            factory = new ActiveMQConnectionFactory("admin","admin","tcp://localhost:61616");

            connection = factory.createConnection();
            //消息的消费者必须启动连接,否支无法处理消息
            connection.start();
            session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
            destination = session.createQueue("fightwk");
            //创建消息消费者对象,在指定的目的地中获取消息
            consumer = session.createConsumer(destination);
            //获取队列中的消息
            message = (TextMessage) consumer.receive();
            //处理文本消息
            resultCode = message.getText();
        }catch(Exception 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();
                }
            }
        }
        return resultCode;
    }

    public static void main(String[] args){
        ConsumerQueue consumer = new ConsumerQueue();
        String messageString = consumer.receiveTextMessage();
        System.out.print("接收的消息内容是:" + messageString);
    }
}

ProduceQueue.java运行截图
在这里插入图片描述在这里插入图片描述ConsumerQueue.java运行截图
在这里插入图片描述在这里插入图片描述

3.2 Topic模式

消息生产者
ProducerTopic.java

package com.fightwk.active;

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;

public class ProducerTopic {
    /**
     * 发送消息到ActiveMQ中,具体的消息内容为参数信息
     * 开发JMS相关代码中,使用的接口类型都是javax.jms包下的类型
     * @param datas 消息内容
     */
    public void sendTextMessage(String datas){
        //连接工厂
        ConnectionFactory factory = null;
        //连接
        Connection connection = null;
        //目的地
        Destination destination = null;
        //会话
        Session session = null;
        //消息发送者
        MessageProducer producer = null;
        //消息对象
        Message message = null;

        try{
            //创建连接工厂,连接ActiveMQ服务的连接工厂
            //创建工厂,构造方法有三个参数,分别是用户名,密码,连接地址
            //无参构造,有默认的连接地址。本地连接
            //单参数构造,五无验证模式,没有用户的认证
            //三参数构造,有认证+指定地址。默认端口是61616.从ActiveMQ的conf/activemq.xml配置文件中查看
            factory = new ActiveMQConnectionFactory("admin","admin","tcp://localhost:61616");
            //通过工厂,创建连接对象
            //创建连接的方法有重载,其中有createConnection(String username,String password)
            //可以再创建连接工厂时,只传递连接地址,不传递用户信息
            connection = factory.createConnection();
            //建议启动连接,消息的发送者不是必须启动连接。消息的消费者必须启动连接
            //producer再发送消息的时候,会检查是否启动了连接,如果未启动,自动启动
            //如果有特殊的配置,建议配置完毕后再启动连接
            connection.start();
            //通过连接对象,创建会话对象
            /*创建会话的时候,必须传递两个参数,分别代表的是否支持事务和如何确认消息处理
             * transacted:是否支持事务,数据类型是boolean.true-支持  false-不支持
             * 		true:支持事务,第二个参数对producer来说默认是无效。建议传递的数据是Session.SESSION_TRANSACTED
             * 		false:不支持事务,常用参数。第二个参数必须传递,且必须有效
             * acknowledgeMode:如何确认消息的处理。使用确认机制实现的
             * 		AUTO_ACKNOWLEDGE:自动确认消息。消息的消费者处理消息后,自动确认。常用。商业开发不推荐
             * 		CLIENT_ACKNOWLEDGE:客户端手动确认。消息的消费者处理后,必须手工确认
             * 		DUPS_OK_ACKNOWLEDGE:有副本的客户端手动确认
             * 				一个消息可以多次处理
             * 				可以降低Session的消耗,再可以容忍重复消息时使用(不推荐使用)
             */
            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
            //创建主题目的地。参数是目的地名称。是目的地的唯一标记

            destination = session.createTopic("fightwk");
            //通过会话对象,创建消息的发送者producer
            //创建的消息发送者,发送的消息一定到指定的目的地中
            //创建producer的时候,可以不提供目的地。在发送消息的时候制定目的地
            producer = session.createProducer(destination);
            //创建文本消息对象,作为具体数据内容的载体
            message = session.createTextMessage(datas);
            //使用producer,发送消息到ActiveMQ中的目的地。如果消息发送失败。抛出异常
            producer.send(message);
            System.out.println("消息已经发送成功....");
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(producer != null){//回收消息发送者
                try {
                    producer.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){
        System.out.println("生产者程序开始启动.....");
        ProducerTopic producer = new ProducerTopic();
        producer.sendTextMessage("我是一个测试的ActiveMQ Topic...");
        System.out.println("生产者程序已经关闭.....");
    }
}

消息消费者代码
ConsumerTopicA.java

package com.fightwk.active;

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;

public class ConsumerTopicA {
    public String receiveTextMessage(){
        String resultCode = "";
        ConnectionFactory factory = null;
        Connection connection = null;
        Session session = null;
        Destination destination = null;
        //消息的消费者,用于接收消息的对象
        MessageConsumer consumer = null;
        TextMessage message = null;

        try{
            factory = new ActiveMQConnectionFactory("admin","admin","tcp://localhost:61616");
            connection = factory.createConnection();
            //消息的消费者必须启动连接,否支无法处理消息
            connection.start();
            session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
            destination = session.createTopic("fightwk");
            //创建消息消费者对象,在制定的目的地中获取消息
            consumer = session.createConsumer(destination);

            message = (TextMessage) consumer.receive();
            resultCode = message.getText();
            /**消费者消息监听开始*/
//			consumer.setMessageListener(new MessageListener() {
//
//				public void onMessage(Message message) {
//					try {
//	                    System.out.println("接收消息  = [" + ((TextMessage) message).getText() + "]");
//	                } catch (JMSException e) {
//	                    e.printStackTrace();
//	                }
//				}
//			});
            //阻塞当前代码。保证listener代码未结束。如果代码结束了,监听器自动关闭
//			System.in.read();
            /**消费者消息监听结束*/
        }catch(Exception 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();
                }
            }
        }
        return resultCode;
    }

    public static void main(String[] args){
        System.out.println("消费者A程序开始启动.....");
        ConsumerTopicA consumerTopicA = new ConsumerTopicA();
        String messageString = consumerTopicA.receiveTextMessage();
        System.out.println("接收的消息内容是:" + messageString);
        System.out.println("消费者A程序已经关闭.....");
    }
}

ConsumerTopicB.java

package com.fightwk.active;

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;

public class ConsumerTopicB {
    public String receiveTextMessage(){
        String resultCode = "";
        ConnectionFactory factory = null;
        Connection connection = null;
        Session session = null;
        Destination destination = null;
        //消息的消费者,用于接收消息的对象
        MessageConsumer consumer = null;
        TextMessage message = null;

        try{
            factory = new ActiveMQConnectionFactory("admin","admin","tcp://localhost:61616");
            connection = factory.createConnection();
            //消息的消费者必须启动连接,否支无法处理消息
            connection.start();
            session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
            destination = session.createTopic("fightwk");
            //创建消息消费者对象,在制定的目的地中获取消息
            consumer = session.createConsumer(destination);
            message = (TextMessage) consumer.receive();
            resultCode = message.getText();       
        }catch(Exception 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();
                }
            }
        }
        return resultCode;
    }
    public static void main(String[] args){
        System.out.println("消费者B程序开始启动.....");
        ConsumerTopicA consumerTopicA = new ConsumerTopicA();
        String messageString = consumerTopicA.receiveTextMessage();
        System.out.println("接收的消息内容是:" + messageString);
        System.out.println("消费者B程序已经关闭.....");
    }
}

运行消息消费者代码
(ps:切记在Topic模式中一定要先运行消费者在运行生产者,不信的话可以自己试试~)
在这里插入图片描述在这里插入图片描述运行生产者代码
在这里插入图片描述在这里插入图片描述
在这里插入图片描述ActiveMQ网站
在这里插入图片描述
这里是作别CSDN博客一年之久的fightwk,从今天起会尽量更新作为巩固知识点的一个途径。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值