1.2.1 ActiveMQ入门(介绍、JMS、安装、使用)

ActiveMQ是什么

ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总想。

ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。

JMS是什么

Java消息服务(Java Message Service,即JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API。

JMS的对象模型

ConnectionFactory 连接工厂
Connection 连接
Session 会话
Destination 目的
MessageProducer 生产者
MessageConsumer 消费者
Message 消息
Broker 消息中间件的实例(ActiveMQ)

JMS的消息模型

Point-to-Point (P2P) / 点对点
在这里插入图片描述
Publish/Subscribe (Pub/Sub) / 主题 (发布订阅)
在这里插入图片描述

JMS的消息结构

在这里插入图片描述

消息头

在这里插入图片描述

消息属性

消息属性可以理解为消息的附加消息头,属性名可以自定义

属性值类型:booleanbyteintlongfloatdoubleString

消息体

在这里插入图片描述

ActiveMQ的特性

  • 支持多种编程语言
  • 支持多种传输协议
  • 有多种持久化方式

ActiveMQ安装

演示环境: Centos7、jdk8、activemq5.15.8
下载地址: http://activemq.apache.org/activemq-5158-release.html
或者cd /tmp,再wget -c http://mirrors.shu.edu.cn/apache/activemq/5.15.8/apache-activemq-5.15.8-bin.tar.gz,如果没有安装wget的话,可以先yum install wget
解压: tar -zxvf apache-activemq-5.15.8-bin.tar.gz -C /var
修改目录名称 mv /var/apache-activemq-5.15.8/ /var/activemq/

启动: ./bin/activemq start
停止:./bin/activemq stop

前面使用命令运行ActiveMQ,但最好的方法是将ActiveMQ作为服务启动,使用system服务将可以确保ActiveMQ能在系统启动时启动。

做成系统服务

1、创建一个systemd服务文件:vi /usr/lib/systemd/system/activemq.service

2、 放入内容

[Unit]
Description=ActiveMQ service
After=network.target

[Service]
Type=forking
ExecStart=/var/activemq/bin/activemq start
ExecStop=/var/activemq/bin/activemq stop
User=root
Group=root
Restart=always
RestartSec=9
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=activemq


[Install]
WantedBy=multi-user.target

3、 找到java命令所在的目录 whereis java,复制路径填入下一步的JAVA_HOME中。

4、设置activemq配置文件/var/activemq/bin/env中的JAVA_HOME

# Location of the java installation
# Specify the location of your java installation using JAVA_HOME, or specify the
# path to the "java" binary using JAVACMD
# (set JAVACMD to "auto" for automatic detection)
JAVA_HOME="/usr/local/java/jdk1.8.0_181"
JAVACMD="auto"

5、 通过systemctl管理activemq启停

  • 启动activemq服务: systemctl start activemq
  • 查看服务状态: systemctl status activemq
  • 创建软件链接:ln -s /usr/lib/systemd/system/activemq.service /etc/systemd/system/multi-user.target.wants/activemq.service
  • 开机自启: systemctl enable activemq
  • 检测是否开启成功(enable): systemctl list-unit-files |grep activemq

6、 防火墙配置,Web管理端口默认为8161,通讯端口默认为61616

  • 添加并重启防火墙
firewall-cmd --zone=public --add-port=8161/tcp --permanent
firewall-cmd --zone=public --add-port=61616/tcp --permanent
systemctl restart firewalld.service
  • 或者直接关闭防火墙: systemctl stop firewalld.service
  • 如果你是阿里云服务器还需要开放控制台里的防火墙端口。

使用ActiveMQ的Web管理平台

ActiveMQ自带有管理平台,在游览器访问http://服务IP:8181/admin即可进入。

ActiveMQ的管理页面默认开启了身份校验

账号:admin

密码:admin

Web管理配置

ActiveMQ的Web管理平台是基于jetty运行,因此在/var/activemq/conf目录可以看到jetty的配置文件。
在这里插入图片描述
修改web管理平台的默认端口,在/var/activemq/conf/jetty.xml中。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在Java中使用ActiveMQ

Maven使用ActiveMQ

添加依赖

<dependencies>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
            <version>5.15.8</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.0</version>
        </dependency>
    </dependencies>

/**
 * 简单生产者
 */
public class Producer {
    public static void main(String[] args) {
        new ProducerThread("tcp://123.57.246.250:61616", "queue1").start();
    }

    static class ProducerThread extends Thread {
        String brokerUrl;
        String destinationUrl;

        public ProducerThread(String brokerUrl, String destinationUrl) {
            this.brokerUrl = brokerUrl;
            this.destinationUrl = destinationUrl;
        }

        @Override
        public void run() {
            ActiveMQConnectionFactory connectionFactory;
            Connection conn;
            Session session;

            try {
                // 1、创建连接工厂
                connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
                // 2、创建连接对象md
                conn = connectionFactory.createConnection();
                conn.start();
                // 3、创建会话
              	//第一个参数:是否开启事务。true:开启事务,第二个参数忽略。
								//第二个参数:当第一个参数为false时,才有意义。消息的应答模式。1、自动应答2、手动应答。自动应答的意思是客户端收到消息后就删除,收到消息不代表正确使用,如果我们要确保消息正确被消费就要手动的。
                session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
                // 4、创建点对点发送的目标
                 Destination destination = session.createQueue(destinationUrl);
                // 5、创建生产者消息
                MessageProducer producer = session.createProducer(destination);
                // 设置生产者的模式,有两种可选 持久化 / 不持久化
                producer.setDeliveryMode(DeliveryMode.PERSISTENT);
                // 6、创建一条文本消息
                String text = "Hello world!";
                TextMessage message = session.createTextMessage(text);
                for (int i = 0; i < 1; i++) {
                    // 7、发送消息
                    producer.send(message);
                }
                // 8、 关闭连接
                session.close();
                conn.close();
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * 简单消费者
 */
// http://activemq.apache.org/consumer-features.html
public class Consumer {
    public static void main(String[] args) {
        new ConsumerThread("tcp://123.57.246.250:61616", "queue1").start();
        new ConsumerThread("tcp://123.57.246.250:61616", "queue1").start();
    }
}

class ConsumerThread extends Thread {

    String brokerUrl;
    String destinationUrl;

    public ConsumerThread(String brokerUrl, String destinationUrl) {
        this.brokerUrl = brokerUrl;
        this.destinationUrl = destinationUrl;
    }

    @Override
    public void run() {
        ActiveMQConnectionFactory connectionFactory;
        Connection conn;
        Session session;
        MessageConsumer consumer;

        try {
            // brokerURL http://activemq.apache.org/connection-configuration-uri.html
            // 1、创建连接工厂
            connectionFactory = new ActiveMQConnectionFactory(this.brokerUrl);
            // 2、创建连接对象
            conn = connectionFactory.createConnection();
            conn.start(); // 一定要启动
            // 3、创建会话(可以创建一个或者多个session)
            session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            // 4、创建点对点接收的目标,queue - 点对点
            Destination destination = session.createQueue(destinationUrl);

            // 5、创建消费者消息 http://activemq.apache.org/destination-options.html
            consumer = session.createConsumer(destination);

            // 6、接收消息(没有消息就持续等待)
            Message message = consumer.receive();
            if (message instanceof TextMessage) {
                System.out.println("收到文本消息:" + ((TextMessage) message).getText());
            } else {
                System.out.println(message);
            }

            consumer.close();
            session.close();
            conn.close();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

输出结果: 收到文本消息:Hello world!

springboot使用ActiveMQ

  1. pom文件导入依赖
	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--直接使用spring-boot-starter-activemq-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <!-- MQTT -->
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-mqtt</artifactId>
        </dependency>
    </dependencies>
  1. 写入配置 application.properties
spring.activemq.broker-url=tcp://123.57.246.250:61616
spring.activemq.user=admin
spring.activemq.password=admin
  1. Producer代码
@SpringBootApplication
public class Producer {

    @Autowired
    private JmsTemplate jmsTemplate;

    @PostConstruct
    public void init() {
        jmsTemplate.convertAndSend("queue1", "Hello Spring 4");
    }

    public static void main(String[] args) {
        SpringApplication.run(Producer.class, args);
    }
}
  1. Consumer代码
@SpringBootApplication
@EnableJms
public class Consumer {

    @JmsListener(destination = "queue1")
    public void receive(String message) {
        System.out.println("收到消息:" + message);
    }

    public static void main(String[] args) {
        SpringApplication.run(Consumer.class, args);
    }
}

手动配置多个ActiveMQ

  1. 需要添加一个JmsConfiguration类
@Configuration
@EnableJms
public class JmsConfiguration {

    /**
     * 连接工厂
     * 配置多个ActiveMQ就把该方法复制一个,改下方法名,修改一些参数即可。
     * @param brokerUrl
     * @param userName
     * @param password
     * @return
     */
    @Bean
    public ConnectionFactory connectionFactory1(@Value("${spring.activemq.broker-url}") String brokerUrl, @Value("${spring.activemq.user}") String userName, @Value("${spring.activemq.password}") String password) {
        return new ActiveMQConnectionFactory(userName, password, brokerUrl);
    }

    /**
     * 连接工厂
     *
     * @param brokerUrl
     * @param userName
     * @param password
     * @return
     */
    @Bean
    public ConnectionFactory connectionFactory2(@Value("${spring.activemq.broker-url}") String brokerUrl, @Value("${spring.activemq.user}") String userName, @Value("${spring.activemq.password}") String password) {
        return new ActiveMQConnectionFactory(userName, password, brokerUrl);
    }

    /**
     * 队列模式的监听容器
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerFactoryQueue(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setConnectionFactory(connectionFactory);
        return bean;
    }

    /**
     * topic 监听
     * @param connectionFactory
     * @return
     */
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerFactoryTopic(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setConnectionFactory(connectionFactory);
        bean.setPubSubDomain(true);
        return bean;
    }

    /**
     * 队列模板
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public JmsTemplate jmsTemplateQueue(ConnectionFactory connectionFactory) {
        return new JmsTemplate(connectionFactory);
    }

    /**
     * 发布订阅模板
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public JmsTemplate jmsTemplatePublish(ConnectionFactory connectionFactory) {
        JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
        jmsTemplate.setPubSubDomain(true);
        return jmsTemplate;
    }

}
  1. Producer代码演示
@SpringBootApplication
public class Producer {

    @Autowired
    private JmsTemplate jmsTemplatePublish;

    @Autowired
    private JmsTemplate jmsTemplateQueue;

    @PostConstruct
    public void send() {
        // 队列模式发送
        jmsTemplatePublish.convertAndSend("topic1", "Hello Spring topic 1");

        // 发布订阅模式发送
        jmsTemplateQueue.send("queue1", new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                MapMessage message = session.createMapMessage();
                message.setString("msg", "Hello Spring xxxx");
                return message;
            }
        });
    }

    public static void main(String[] args) {
        SpringApplication.run(Producer.class, args);
    }
}
  1. Consumer代码演示
@SpringBootApplication
public class Consumer {

    @JmsListener(destination = "queue1", containerFactory = "jmsListenerContainerFactoryQueue")
    public void receiveQueue(Message message) throws JMSException {
        if (message instanceof TextMessage) {
            System.out.println("收到文本消息:" + ((TextMessage) message).getText());
        } else if (message instanceof ActiveMQMapMessage) {
            System.out.println("收到Map消息:" + ((ActiveMQMapMessage) message).getContentMap());
        } else {
            System.out.println(message);
        }
    }

    @JmsListener(destination = "topic1", containerFactory = "jmsListenerContainerFactoryTopic")
    public void receiveTopic(String message) {
        System.out.println("收到订阅消息:" + message);
    }

    public static void main(String[] args) {
        SpringApplication.run(Consumer.class, args);
    }
}
发布了47 篇原创文章 · 获赞 15 · 访问量 7944

猜你喜欢

转载自blog.csdn.net/weixin_43871142/article/details/104801036
今日推荐