首发时间:2019-05-16


ActiveMQ

介绍

  • ActiveMQ是Apache旗下的一款开源的消息队列(消息中间件MOM,Message Oriented Middleware)
  • 它完全支持JMS,支持JMS1.1和J2EE 1.4 规范。
  • 支持多种网络协议。
  • 兼容多种语言(C,C++,Java,Python,PHP)
  • 可以方便地与spring进行整合开发。
  • (其他的一些说的太多可能也不是很懂,以后想了解再自己了解吧,毕竟这里只是个小博文。)

下载、安装和初次运行

1.下载:从ActiveMQ官网下载ActiveMQ,地址:http://activemq.apache.org/download.html



2.安装:下载下来的是一个压缩包,解压即安装,直接解压到一个目录即可;

3.初次运行:(在启动ActiveMQ前,请先要已经安装和配置好JDK)在windows版本的activemq中在activeMQ/bin下面有两个目录,为win32,win64,根据自己的系统位数进入不同的目录,然后直接双击目录下的activemq.bat (在linux中为: ./activemq start)

4.检测是否启动:ActiveMQ默认使用61616端口提供JMS服务,使用8161端口提供管理控制台服务,我们可以直接访问activemq的管理控制台网页来确定是否已经开始服务:localhost:8161/admin,默认的用户名和密码都是admin,输入后将进入如下的界面:



5.关闭ActiveMQ:windosw中直接ctrl+c关闭cmd窗口(在linux中: ./activemq stop)

Java上初次使用activeMQ

这里以PTP模型的生产者和消费者的消息传递为例。

1.首先导入依赖包,以maven为例:

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

2.生产者发送消息(以PTP方式为例):【这里是符合上面的“JMS应用开发基本步骤”的】

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class Producer { public static void main(String[] args) throws JMSException {
//1.创建connectionfacoty,参数是activemq的服务地址,前缀tcp代表是tcp连接
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
//2.使用ConnectionFactory创建connnect,并启动connnect
Connection connection = connectionFactory.createConnection();
connection.start();
//3.使用Connection创建session,第一个参数是是否使用事务,第二个参数是确认机制
Session session = connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
//4.创建目的地(这里以PTP为例,所以目的地是一个Queue),参数是Queue的名字
Destination destination = session.createQueue("tempqueue");
//5.创建生产者,第一个参数是目的地,此时创建的生产者要与目的地进行绑定。
MessageProducer producer = session.createProducer(destination);
//6.使用session创建消息,这里使用TEXT类型的消息
TextMessage textMessage = session.createTextMessage("hello world!");
//7.生产者发送消息
producer.send(textMessage);
//8.提交事务
session.commit();
//9.关闭资源
session.close();
connection.close();
}
}

3.消费者接收消息(以PTP方式为例):

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class Consumer {
public static void main(String[] args) throws JMSException {
//1.创建connectionfacoty
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
//2.创建connnect,并启动connnect
Connection connection = connectionFactory.createConnection();
connection.start();
//3.创建session,第一个参数是是否使用事务,第二个参数是确认机制
Session session = connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
//4.创建目的地【消费者与生产者的目的地相同才能进行消息传递】
Destination destination = session.createQueue("tempqueue");
//5.创建消费者,第一个参数是目的地,此时创建的消费者要与目的地进行绑定。
MessageConsumer consumer = session.createConsumer(destination);
//6.使用消费者接受消息消息
TextMessage message = (TextMessage) consumer.receive();
System.out.println(message.getText());
//8.提交事务
session.commit();
//9.关闭资源
session.close();
connection.close();
}
}

上述代码解析:

1.前半部分代码都是一样的,都是创建ConnectionFactory,Connection,Session

2.然后创建目的地Destination,这个目的地就是要把消息存储到哪里和从哪里取消息。

3.如果是生产者,那么由Session来创建生产者,创建的时候传入一个目的地,来与生产者绑定,生产者调用send发送的消息都会存储到目的地中。生产者发送的消息需要使用Session来创建,调用createXXXMessage来创建消息,创建什么类型的消息取决于使用什么方法来创建。

4.如果是消费者,那么由Session来创建消费者,创建的时候传入一个消费者,来与消费者绑定,消费者调用receive时会从目的地中获取消息。获取到的结果是一个XXXMessage,通常需要转成对应类型的Message,然后再调用对应的获取消息体的方法来获取消息体。例如TextMessage类型的消息要获取消息体需要调用getText()。

5.如果使用了事务,那么需要session.commit()

6.最后关闭所有资源

设置请求属性:

设置标准属性:使用消息调用setJMS开头的方法。【要注意的是为了避免发生过期的消息,任何直接通过编程方式来调用setJMSExpiration()方法都会被忽略。 】

设置自定义属性:使用消息调用setXXXProperty的方法。



接受属性:

可靠性机制

在上面的概念学习中你应该了解到,如果不使用事务来进行消息确定,那么需要手动使用消息来调用acknowledge来确认消息。【而且这时候是在会话层进行确认,所以在这个会话中只要一条消息进行了确认,其他消息也会被确认(即使他收了两条消息只确认了一条)】



当使用了事务的时候,代码中就不要使用acknowledge了,会影响消息的确认。

事务

在上面的概念学习有提到了事务,事务可以使一系列操作共同成功或失败。下面来演示一下事务的使用。

1.首先,在创建Session的时候第一个参数是是否使用事务,要使用事务需要赋值TRUE。

2.提交事务使用session.commit(),回滚是session.rollback()

3.对于生产者,事务是确保消息发送的一致性;对于消费者,事务是确保消息消费的一致性,

4.对于事务的测试可以使用单步运行来测试,在发消息处打断点,测试未commit时消费者是否能取到消息。



消息消费方式

在上面的概念学习中有谈到消费者消费消息的两种方式,一种是堵塞的receive,一种是监听器。监听器与receive最大的区别是如果没有,那么监听器不会等,而receive会等。所以监听器适用于不希望堵塞程度运行的场景。

receive

上面的代码都是使用堵塞的receive来接收的,你应该可以留意到当运行了消费者后,没有取到消息的时候会一直堵塞在那里。receive也可以设置阻塞时间,时间到了就不再等了。

监听器:

public class Consumer {
public static void main(String[] args) throws JMSException {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("tempqueue2");
MessageConsumer consumer = session.createConsumer(destination);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
TextMessage msg = (TextMessage) message;
try {
System.out.println("..."+msg.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
session.commit();
session.close();
connection.close();
}
}

消息类型

在上面有介绍到消息体有不同的类型,TextMessage,MapMessage等。

不同的消息类似影响存储到消息队列的消息的格式,也影响取消息的方式,取消息的方式要与消息类型对应。

TextMessage:数据类型类似于字符串。使用getText()来获取数据。





MapMessage:数据类型类似于Map。使用getXXX(key)来获取数据。





发布/订阅模式

上面主要讲的都是PTP模式,下面来讲一下发布/订阅模式。在上面的概念学习中,有涉及到多消费者广播、持久化订阅,下面将演示这些概念的实际使用。

非持久订阅

先演示非持久订阅的,由于非持久订阅只能发送给在线的消费者,所以先运行消费者(多个)。【非持久订阅的消息接收与PTP一样可以使用receive】



然后创建生产者发生消息:



注意:在非持久化订阅中,通常要使消费者持续receive,所以通常使用while循环来接受消息。

Message message = consumer.receive();
while(message!=null){
TextMessage txtMsg = (TextMessage)message;
sysout(textmsg.getText());
message = consumer.receive();
}

持久化订阅

要进行持久化订阅,首先要将生产者的发送模式改成持久化模式,这个设置要在connection.start()之前



然后消费者要创建持久订阅器,而且要在消息发送之前先运行一次把持久化订阅器注册到消息队列上。

【注意:需要在连接上设置消费者ID,用来识别消费者,持久化订阅器识别消费者依靠消费者ID,如果不设置,那么下一次“上线”的时候,由于消费者ID会变化,导致订阅器无法与消费者进行关联】

public class Consumer {
public static void main(String[] args) throws JMSException {
//1.创建connectionfacoty
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
//2.创建connnect,并启动connnect
Connection connection = connectionFactory.createConnection();
connection.setClientID("001"); //3.创建session,第一个参数是是否使用事务,第二个参数是确认机制
Session session = connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createTopic("tempTopic");
TopicSubscriber s1 = session.createDurableSubscriber((Topic) destination, "s1");
connection.start();
Message msg = s1.receive();
while (msg!=null){
TextMessage txtmsg = (TextMessage) msg;
System.out.println(txtmsg.getText());
session.commit(); // 由于此时使用了while,所以要在里面commit
msg= s1.receive();
}
session.close();
connection.close();
}
}

Broker

Broker是ActiveMQ服务器实例。

在使用独立的ActiveMQ程序的时候,有时候会创建不同需求的服务器实例,通常来说都是使用某个配置文件进行创建。

而也是可以通过代码内建一个Broker的,内建的Broker比较小巧,适用于一些希望把Broker整合到项目中的场景。

1.通过BrokerService创建:



上述代码报错java.lang.NoClassDefFoundError:com/fasterxml/jackson/databind/ObjectMapper时可能缺乏以下依赖包:

        <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>

2.通过BrokerFactory创建:



使用BrokerFactory创建时需要一个配置文件,这个配置文件的路径要被传入到BrokerFactory中,在上面的代码中就是properties:broker.properties,配置文件里面是这个Broker的参数。

下面是broker.properties的一个例子:

useJms=true
persistent=false
brokerName=FactoryBroker

对于能配置什么,可以参考使用BrokerService创建Broker时的setXXX。

整合spring开发

现在很多的项目都使用到了Spring,所以这里也讲一下与Spring的整合。

首先理一下,ActiveMQ有什么可以交给Spring来管理的?可以说可以交给Spring管理的只有Destination,ConnectionFactory,Connection和Broker,只有这几个实例的复用性比较强,这几个的管理会在JmsTemplate使用中展示。

如果你学过Hibernate之类的框架,你应该知道Spring对Hibernate提供HibernateTemplate来整合,HibernateTemplate封装了Hibernate的一些方法,简化了使用,在使用HibernateTemplate的时候,dao层的类需要继承HibernateDaoSupport,然后同时需要在类中注入Connection,这样HibernateTemplate才可以正常工作。JmsTemplate类似于HibernateTemplate,不过它是面向JMS的。

使用JmsTemplate

1.首先要编写Spring配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--管理destination-->
<bean id="destinationQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg name="name" value="spring-queue"/> <!-- 目的地名称 -->
</bean>
<bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg name="name" value="spring-topic"/> <!-- 目的地名称 -->
</bean> <!--管理connectionFactory-->
<bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>tcp://localhost:61616</value>
</property>
</bean>
</property>
<property name="maxConnections" value="100"></property>
</bean> <!--管理JmsTemplate-->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsFactory"></property>
<property name="defaultDestination" ref="destinationQueue"></property>
<property name="messageConverter">
<bean class="org.springframework.jms.support.converter.SimpleMessageConverter"></bean>
</property>
</bean> </beans>

2.然后创建测试类:


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.annotation.Resource;
import javax.jms.*; @RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试
@ContextConfiguration(locations={"classpath:applicationContext.xml"}) //加载配置文件
public class JmsTemplateDemo {
@Autowired
private JmsTemplate jmsTemplate;
@Resource(name="destinationQueue")
private Destination destinationQueue;
//发送
@Test
public void send() throws JMSException {
String msg = "hello world!";
jmsTemplate.send(destinationQueue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(msg);
}
}); }
//接收
@Test
public void recv() throws JMSException {
TextMessage message = (TextMessage) jmsTemplate.receive(destinationQueue);
System.out.println(message.getText());
}
}

在上面的代码中可以使用jmsTemplate.send来发送消息,使用jmsTemplate.receive来接收消息。对于消息确认和事务管理则不需要关心,JmsTemplate会自己处理的。

监听器

在上面的JmsTemplate接收消息中使用了receive来接收消息,Spring还支持使用监听器来接收消息,配置监听器,来达到一有消息就执行某些操作,这样就省去了消费者的代码。

1.首先,需要需要在spring配置文件中配置DefaultMessageListenerContainer【还有其他几种监听器】:

    <!--配置DefaultMessageListenerContainer -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsFactory"></property>
<!--监听器 -->
<property name="messageListener" ref="myMessageListener"></property>
<!--监听哪个目的地 -->
<property name="destination" ref="destinationQueue"></property>
</bean> <!--配置监听器-->
<bean id="myMessageListener" class="withspring.MyMessageListener">
</bean>

2.然后,定义一个监听器:

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage; public class MyMessageListener implements MessageListener {
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
TextMessage txtMsg = (TextMessage) message;
String msg = txtMsg.getText();
System.out.println("recv:"+ msg);
} catch (JMSException e) {
throw new RuntimeException(e);
}
} else {
throw new IllegalArgumentException("消息类型错误!");
}
}
}

3.最后,运行随便在这个项目中的一个发送消息的测试方法。

使用spring集合Broker

1.通过BrokerService:

    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="broker" class="org.apache.activemq.broker.BrokerService" init-method="start" destroy-method="stop">
<property name="brokerName" value="SpringBroker"/>
<property name="persistent" value="false"/>
<property name="transportConnectorURIs">
<list>
<value>tcp://localhost:61616</value>
</list>
</property>
</bean>
</beans>

【还可以通过BrokerFactory或BrokerFactoryBean来创建,这里省略】

【当然,上面的是比较简单的,没有进行权限管理,你也登录不了管理页,想要确定是否创建成功可以监听接口也可以进行生产和消费消息】


后续可扩展内容

这里只是一篇小博客,写不了太多东西。如果想要了解更精细,可以去买书来看。
下面写一下后续可扩展学习的内容,学不学由个人考虑。


* 传输协议【上面介绍了tcp://localhost:61616,其实还可以允许非TCP的连接】
* 消息存储持久化【消息是怎么进行存储的】
* KahaDB
* AMQ
* JDBC
* 内存存储
* 部署与集群
* 优化


消息队列的使用<二>:ActiveMQ的基本使用(Java)的更多相关文章

  1. 消息队列中间件(二)使用 ActiveMQ

    ActiveMQ 介绍 Active MQ 是由 Apache 出品的一款流行的功能强大的开源消息中间件,它速度快,支持跨语言的客户端,具有易于使用的企业集成模式和许多的高级功能,同时完全支持 JSM ...

  2. 消息队列开发记录笔记-ActiveMQ

    1.下载ActiveMQ 去官方网站下载:http://activemq.apache.org/ 2.运行ActiveMQ 解压缩apache-activemq-5.5.1-bin.zip,然后双击a ...

  3. 消息队列:快速上手ActiveMQ消息队列的JMS方式使用(两种模式:Topic和Queue的消息推送和订阅)

    1.实现功能 希望使用一套API,实现两种模式下的消息发送和接收功能,方便业务程序调用 1.发送Topic 2.发送Queue 3.接收Topic 4.接收Queue 2.接口设计 根据功能设计公共调 ...

  4. SpringBoot日记——MQ消息队列整合(二)

    基于第一篇文章搭建好环境以后,我们这篇文章继续介绍如何在springboot中使用RabbitMQ. 1).单播:添加好pom文件和自定义配置后,来看: @Autowired RabbitTempla ...

  5. 一起talk C栗子吧(第九十八回:C语言实例--使用消息队列进行进程间通信二)

    各位看官们,大家好,上一回中咱们说的是使用消息队列进行进程间通信的样例.这一回咱们接着上一回的内容继续说使用消息队列进行进程间通信.闲话休提.言归正转.让我们一起talk C栗子吧! 我们在上一回中介 ...

  6. 消息队列RabbitMQ(二):RabbitMQ的系统架构概述

    前言 RabbitMQ是基于AMQP协议的,要想深入理解RabbitMQ,就必须先了解AMQP是个什么东东? AMQP协议 AMQP即Advanced Message Queuing Protocol ...

  7. 消息队列系列(二):.Rabbitmq的使用及Web监控工具使用

    一.文档资料        1.官方网站:http://www.rabbitmq.com/        2.安装教程:http://www.rabbitmq.com/install-windows. ...

  8. RabbitMQ消息队列(十二)-性能测试

    硬件配置 宿主机用的联想3850X6的服务器四颗E7-4850v3的处理器,DDR4内存,两块1.25TB的pcie固态.在宿主机上使用的事esxi5.5的虚拟化平台,在子系统中安装RabbitMQ和 ...

  9. Rabbit五种消息队列学习(二) – 简单队列

    队列结构图 P:消息的生产者 C:消息的消费者 红色:队列 生产者将消息发送到队列,消费者从队列中获取消息. 测试 1.连接MQ public static Connection getConnect ...

随机推荐

  1. 基于Django的Rest Framework框架的视图组件

    本文目录 一 基本视图 二 mixin类和generice类编写视图 三 使用generics 下ListCreateAPIView,RetrieveUpdateDestroyAPIView 四 使用 ...

  2. React: React的属性验证机制

    一.简介 在开发中,属性变量类型的验证,几乎是任何语言都必须关注的问题,因为如果传入的数据类型不对,轻者程序运行仅仅是给出警告⚠️,严重的会直接导致程序中断,APP闪退或者web页面挂掉,这是很严重的 ...

  3. 用Python做个海量小姐姐素描图

    素描作为一种近乎完美的表现手法有其独特的魅力,随着数字技术的发展,素描早已不再是专业绘画师的专利,今天这篇文章就来讲一讲如何使用python批量获取小姐姐素描画像.文章共分两部分: 第一部分介绍两种使 ...

  4. IT兄弟连 HTML5教程 HTML5技术的应用现状及HTML5平台的兴起

    HTML5的优良特性很快被各种类型的网站利用,比如文件拖拽到网页上传功能,多数即使用HTML5提供的新属性就可以完成,来实现素材的免插件拖放.因此,HTML5技术实际上在国内已经获得了较广泛的应用与支 ...

  5. python 操作zookeeper详解

    ZooKeeper 简介 ZooKeeper 是一个分布式的.开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 Hbase 的重要组件.它是一 ...

  6. SPU和SKU介绍及区别

    一.spu概念 SPU = Standard Product Unit (标准化产品单元) SPU是商品信息聚合的最小单位,是一组可复用.易检索的标准化信息的集合,该集合描述了一个产品的特性.通俗点讲 ...

  7. JMS消息传递类型特点介绍

    对于消息的传递有两种类型: 一种是点对点的,即一个生产者和一个消费者一一对应: 另一种是发布/ 订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进 行接收. 特点介绍: 点到点模型点对点传 ...

  8. Zookeeper学习记录及Java客户端连接示例

    1. Zookeeper 1.1 简介 ZooKeeper is a centralized service for maintaining configuration information, na ...

  9. Java SPI机制实战详解及源码分析

    背景介绍 提起SPI机制,可能很多人不太熟悉,它是由JDK直接提供的,全称为:Service Provider Interface.而在平时的使用过程中也很少遇到,但如果你阅读一些框架的源码时,会发现 ...

  10. iOS 应用程序启动时要做什么

    当您的应用程序启动(无论是在前台或后台),使用您的应用程序委托application:willFinishLaunchingWithOptions:和application:didFinishLaun ...