ActiveMQ介绍、使用并与Spring整合

原创 2018年04月15日 16:24:44


一、ActiveMQ

1.1 什么是ActiveMQ

ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ是一个完全支持JMS1.1J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。

主要特点:

  1. 多种语言和协议编写客户端。语言: Java, C, C++, C#, Ruby, Perl, Python, PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP
  2. 完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)
  3. 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性
  4. 通过了常见J2EE服务器(如 Geronimo,JBoss 4, GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上
  5. 支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
  6. 支持通过JDBC和journal提供高速的消息持久化
  7. 从设计上保证了高性能的集群,客户端-服务器,点对点
  8. 支持Ajax
  9. 支持与Axis的整合
  10. 可以很容易得调用内嵌JMS provider,进行测试

1.2 消息形式

  • 点对点模式,即一个生产者和一个消费者一一对应

  • 发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收

JMS定义了五种不同的消息正文格式,以及调用的消息类型,允许你发送并接收以一些不同形式的数据,提供现有消息格式的一些级别的兼容性。

  • StreamMessage – Java原始值的数据流

  • MapMessage–键值对

  • TextMessage–字符串对象 (主要使用,什么都可以转JSON字符串)

  • ObjectMessage–序列化的 Java对象

  • BytesMessage–字节的数据流


二、安装ActiveMQ

本次测试版本为当前最新的ActiveMQ 5.15.3 Release点击下载

解压并放在usr/local目录下:

root@ubuntu:/home/wxs# tar zxvf apache-activemq-5.15.3-bin.tar.gz 
root@ubuntu:/home/wxs# mv apache-activemq-5.15.3 /usr/local/activemq
root@ubuntu:/home/wxs# cd /usr/local/activemq/
root@ubuntu:/usr/local/activemq# ls
activemq-all-5.15.3.jar  conf  docs      lib      NOTICE      webapps
bin                      data  examples  LICENSE  README.txt  webapps-demo

启动ActiveMQ(需要jdk支持):

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

root@ubuntu:/usr/local/activemq# cd bin/
root@ubuntu:/usr/local/activemq/bin# ./activemq start
INFO: Loading '/usr/local/activemq//bin/env'
INFO: Using java '/usr/local/jdk1.8.0_161/bin/java'
INFO: Starting - inspect logfiles specified in logging.properties and log4j.properties to get details
INFO: pidfile created : '/usr/local/activemq//data/activemq.pid' (pid '6914')

ActiveMQ默认运行在8161端口,点击首页的Manage ActiveMQ broker进入后台管理系统,用户名:admin,密码:admin.


三、Queue

前面说过ActiveMQ有两种消息模式,即:

  • 点对点模式,即一个生产者和一个消费者一一对应

  • 发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收

首先介绍下点对点模式,即Queue

首先导入ActiveMQ依赖:

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

3.1 Producer

首先我们编写下消息的发布者(Producer),因为ActiveMQ遵循JMS规范,所以步骤比较繁琐,步骤如下:

  1. 创建一个连接工厂对象,指定服务IP和端口
  2. 使用工厂对象创建Collection对象
  3. 开启连接
  4. 创建Session对象
  5. 使用Session对象创建Destination对象
  6. 使用Session对象创建Producer对象
  7. 创建Message对象
  8. 发送消息
  9. 关闭资源

编写一个测试方法:

@Test
public void testQueueProducer() throws Exception {
    //1、创建一个连接工厂对象,指定服务IP和端口
    // 这里的端口不是8161,而是ActiveMQ服务端口,默认为61616
    String brokerURL = "tcp://192.168.30.155:61616";
    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerURL);
    //2、使用工厂对象创建Collection对象
    Connection connection = connectionFactory.createConnection();
    //3、开启连接,调用Collection.start()
    connection.start();
    //4、创建Session对象
    // 参数1:是否开启事务,如果为true,参数2无效
    // 参数2:应答模式,自动应答/手动应答,一般自动应答即可
    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    //5、使用Session对象创建Destination对象(实现类:queue或topic)
    Queue queue = session.createQueue("test-queue");
    //6、使用Session对象创建Producer对象
    MessageProducer producer = session.createProducer(queue);
    //7、创建Message对象
    TextMessage message = session.createTextMessage("It just a test queue...");
    //8、发送消息
    producer.send(message);
    //9、关闭资源
    producer.close();
    session.close();
    connection.close();
}

执行后查看ActiveMQ后台,选择Queue选项卡可以看到我们创建的Queue对象test-queue:

点进去可以看到发送的消息内容:

3.2 Consumer

现在我们已经把消息发送出去了,但是还没有消费者去接收这个消息,下面开始编写消费者,步骤如下:

  1. 创建一个连接工厂对象,指定服务IP和端口
  2. 使用工厂对象创建Collection对象
  3. 开启连接
  4. 创建Session对象
  5. 使用Session对象创建Destination对象
  6. 使用Session对象创建Consumer对象
  7. 接收消息
  8. 关闭资源

可以看到1~5步和之前都是一样的,编写测试方法:

@Test
public void testQueueConsumer() throws Exception {
    //1、创建一个连接工厂对象,指定服务IP和端口
    // 这里的端口不是8161,而是ActiveMQ服务端口,默认为61616
    String brokerURL = "tcp://192.168.30.155:61616";
    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerURL);
    //2、使用工厂对象创建Collection对象
    Connection connection = connectionFactory.createConnection();
    //3、开启连接,调用Collection.start()
    connection.start();
    //4、创建Session对象
    // 参数1:是否开启事务,如果为true,参数2无效
    // 参数2:应答模式,自动应答/手动应答,自动应答即可
    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    //5、使用Session对象创建Destination对象(queue或topic)
    Queue queue = session.createQueue("test-queue");
    //6、使用Session对象创建一个Consumer对象
    MessageConsumer consumer = session.createConsumer(queue);
    //7、接收消息
    consumer.setMessageListener(message -> {
        try {
            TextMessage msg = (TextMessage) message;
            System.out.println("接收到消息:" + msg.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    });
    //阻塞程序,避免结束
    System.in.read();
    //8、关闭资源
    consumer.close();
    session.close();
    connection.close();
}

运行程序,接收到了之前的消息:

此时重新查看后台,发现Number Of Pending Messages 的值已经变成0,说明刚刚那条消息已经被消费掉了,Number Of Consumers 值变为了1。


四、Topic

下面介绍下发布/订阅模式,即Topic,当一个生产者发送了消息后。多个订阅了该生产者的消费者都会收到消息。

使用Queue时,因为是一对一,所以消费者没有接收的话消息会被保存到ActiveMQ后台,我们可以查看得到,如上面的图示。

但是Topic不一样,ActiveMQ后台是不会保存消息的,因此如果消费者没有接收的话,这个消息就丢失了

因此,我们必须先启动消费者,生产者再发送消息,消费者我才能收到。

4.1 Producer

Topic的生产者和Queue生产者的步骤几乎一样,只是第5步创建Destination对象的实现类修改为Topic即可:

@Test
public void testTopicProducer() throws Exception {
    //1、创建一个连接工厂对象,指定服务IP和端口
    // 这里的端口不是8161,而是ActiveMQ服务端口,默认为61616
    String brokerURL = "tcp://192.168.30.155:61616";
    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerURL);
    //2、使用工厂对象创建Collection对象
    Connection connection = connectionFactory.createConnection();
    //3、开启连接,调用Collection.start()
    connection.start();
    //4、创建Session对象
    // 参数1:是否开启事务,如果为true,参数2无效
    // 参数2:应答模式,自动应答/手动应答,自动应答即可
    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    //5、使用Session对象创建Destination对象(queue或topic)
    Topic topic = session.createTopic("test-topic");
    //6、使用Session对象创建一个Producer对象
    MessageProducer producer = session.createProducer(topic);
    //7、创建一个Message对象
    TextMessage message = session.createTextMessage("It just a test topic...");
    //8、发送消息
    producer.send(message);
    //9、关闭资源
    producer.close();
    session.close();
    connection.close();
}

进入后台查看,test-topic拥有0个消费者,1个消息入队,0个消息入队。前面说过ActiveMQ后台是不会保存Topic的消息的,所以我们刚刚发送的消息因为没有消费者就丢失了。

4.2 Consumer

和Queue的Consumer差不多,只是修改第5步改为创建Topic即可:

@Test
public void testTopicConsumer() throws Exception {
    //1、创建一个连接工厂对象,指定服务IP和端口
    // 这里的端口不是8161,而是ActiveMQ服务端口,默认为61616
    String brokerURL = "tcp://192.168.30.155:61616";
    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerURL);
    //2、使用工厂对象创建Collection对象
    Connection connection = connectionFactory.createConnection();
    //3、开启连接,调用Collection.start()
    connection.start();
    //4、创建Session对象
    // 参数1:是否开启事务,如果为true,参数2无效
    // 参数2:应答模式,自动应答/手动应答,自动应答即可
    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    //5、使用Session对象创建Destination对象(queue或topic)
    Topic topic = session.createTopic("test-topic");
    //6、使用Session对象创建一个Consumer对象
    MessageConsumer consumer = session.createConsumer(topic);
    //7、接收消息
    consumer.setMessageListener(message -> {
        try {
            TextMessage msg = (TextMessage) message;
            System.out.println("接收到消息:" + msg.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    });
    //阻塞程序,避免结束
    System.in.read();
    //8、关闭资源
    consumer.close();
    session.close();
    connection.close();
}

五、与Spring整合

与spring整合,除了原本的activemq-all外,还需导入spring-context-supportspring-jms包,如果Spring为5.0+,需要javax.jms-api依赖:

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-all</artifactId>
    <version>5.15.3</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.0.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jms</artifactId>
    <version>5.0.4.RELEASE</version>
</dependency>
<!-- Spring 5.0及以上需要添加 -->
<dependency>
    <groupId>javax.jms</groupId>
    <artifactId>javax.jms-api</artifactId>
    <version>2.0.1</version>
</dependency>

在配置文件cfg.properties中添加ActiveMQ的相关信息:

activemq.broker_url=tcp://192.168.30.155:61616
activemq.queue_name=test-queue
activemq.topic_name=test-topic

编写spring配置文件applicationContext-activemq.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:cfg.properties"/>

    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="${activemq.broker_url}" />
    </bean>

    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
    <bean id="connectionFactory"
          class="org.springframework.jms.connection.SingleConnectionFactory">
        <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
        <property name="targetConnectionFactory" ref="targetConnectionFactory" />
    </bean>

    <!-- Queue模式 -->
    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg name="name" value="${activemq.queue_name}"/>
    </bean>
    <!--Topic模式 -->
    <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg name="name" value="${activemq.topic_name}"/>
    </bean>

    <!-- 配置生产者 -->
    <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
        <property name="connectionFactory" ref="connectionFactory" />
    </bean>
</beans>

配置文件中核心就是jmsTemplate,因为MQ中间件不止ActiveMQ一中,因此只要符合JSM规范,则都可以使用jmsTemplate来管理,只需要修改底层的实现就可以了(即targetConnectionFactory)。

在配置文件中还准备了两个Destination对象,分别是Queue模式和Topic模式。

5.1 Producer

编写一个生产者的示例代码,步骤大概如下:

  1. 加载容器
  2. 从容器中获取jmsTemplate对象
  3. 从容器中获取Destination对象
  4. 发送消息
@Test
public void testProducer() {
    // 1、加载Spring容器
    ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml");
    // 2、获取jmsTemplate对象
    JmsTemplate jmsTemplate = ac.getBean(JmsTemplate.class);
    // 3、获取Destination对象(以Queue模式为例)
    Destination destination = (Destination)ac.getBean("queueDestination");
    //Destination destination = (Destination)ac.getBean("topicDestination");
    // 4、发送消息
    jmsTemplate.send(destination, session -> session.createTextMessage("这是Spring与ActiveMQ整合的测试消息"));
}

5.1 Consumer

首先需要自定义一个实现MessageListener的类,在其中打印一句话:

import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class MyMessageListener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
            TextMessage textMessage = (TextMessage)message;
            System.out.println("收到消息:" + textMessage.getText());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在Spring容器中首先要注入MyMessageListener,然后配置一个DefaultMessageListenerContainer,指定connectionFactorydestinationmessageListener

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:cfg.properties"/>

    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="${activemq.broker_url}" />
    </bean>

    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
    <bean id="connectionFactory"
          class="org.springframework.jms.connection.SingleConnectionFactory">
        <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
        <property name="targetConnectionFactory" ref="targetConnectionFactory" />
    </bean>

    <!-- Queue模式 -->
    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg name="name" value="${activemq.queue_name}"/>
    </bean>
    <!--&lt;!&ndash;Topic模式 &ndash;&gt;-->
    <!--<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">-->
        <!--<constructor-arg name="name" value="${activemq.topic_name}"/>-->
    <!--</bean>-->

    <!-- 配置消费者 -->
    <bean id="myMessageListener" class="jit.wxs.search.activemq.MyMessageListener"/>
    <!-- 消息监听容器 -->
    <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="destination" ref="queueDestination" />
        <property name="messageListener" ref="myMessageListener" />
    </bean>
</beans>

编写测试代码:

@Test
public void activeMQConsumer() throws Exception{
    ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml");
    System.in.read();
}

先启动该测试方法,然后当生产者运行后,消费者收到消息:


参考项目:e3mall

版权声明:本文为本人原创文章,未经本人允许不得转载,谢谢。 https://blog.csdn.net/yuanlaijike/article/details/79950330

ActiveMQ安装使用与spring整合配置教程

1      ActiveMQ介绍 1.1    什么是ActiveMQ          ActiveMQ是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS...
  • qq_22075041
  • qq_22075041
  • 2017-08-26 16:20:41
  • 1632

ActiveMQ介绍及Spring整合实例

前言ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。主要解决进场通讯,应用耦...
  • poorCoder_
  • poorCoder_
  • 2017-03-10 10:36:37
  • 1643

activemq + spring

  • 2014年12月05日 15:04
  • 10.03MB
  • 下载

Spring整合ActiveMQ实现简单的消息队列

Spring整合ActiveMQ实现简单的消息队列 JMS简介 JMS(Java Message Service),Java消息服务。主要用于在生产者和消费者之间进行消息传送,生产者负责生产消息,...
  • weihao_
  • weihao_
  • 2017-07-05 16:37:33
  • 998

Spring整合activemq

  • 2018年04月12日 16:33
  • 50KB
  • 下载

activeMq整合spring所需jar包

  • 2017年10月10日 11:53
  • 19.66MB
  • 下载

activemq使用系列: spring与activemq的整合

我们先从消息生产者这一端开始整合 创建一个maven工程结构如下 我的pom文件如下 ...
  • u011325787
  • u011325787
  • 2016-05-16 03:47:24
  • 2749

Freemarker介绍、使用并与Spring整合

一、什么是Freemarker 1.1 介绍 1.2 入门程序 二、基本语法 2.1 取Map中Key 2.2 取POJO中属性 2.3 取集合中元素 2.4 取循环中下标 2.5 判断 2...
  • yuanlaijike
  • yuanlaijike
  • 2018-04-16 11:07:17
  • 11

ActiveMQ实例

  • 2017年12月21日 18:00
  • 20.76MB
  • 下载

spring 整合 activemq 配置文件

  • xiuye2015
  • xiuye2015
  • 2016-08-03 10:21:34
  • 969
收藏助手
不良信息举报
您举报文章:ActiveMQ介绍、使用并与Spring整合
举报原因:
原因补充:

(最多只允许输入30个字)