学习目标
什么是ActiveMQ
安装ActiveMQ
应用ActiveMQ
Spring整合ActiveMQ
1.什么是ActiveMQ?
1.1.什么是mq
消息队列(MessageQueue,简称MQ):是在消息的传输过程中保存消息的容器,其主要用途:不同服务之间通信。MQ框架非常之多,比较流行的有RabbitMq、ActiveMq、ZeroMq、kafka,以及阿里开源的RocketMQ。
1.2.为什么要使用MQ ?
1.2.1.解耦
传统模式:系统间耦合性太强,如图所示,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!
中间件模式:将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而系统A不需要做任何修改。
1.2.2.异步
传统模式: 一些非必要的业务逻辑以同步的方式运行,太耗费时间
中间件模式: 将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度
1.2.3.削峰
传统模式:并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常
中间件模式: 系统A慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息或者只处理前100条消息。
1.3.ActiveMQ介绍
1.3.1.什么是ActiveMQ?
ActiveMQ:是Apache软件基金会所研发的开放源代码消息中间件;由于ActiveMQ是一个纯Java程序,因此只需要操作系统支持Java虚拟机,ActiveMQ便可执行。
1.3.2.消息传递方式
2.安装ActiveMQ
2.1.下载
ActiveMQ官网:http://activemq.apache.org/download.html下载
2.2.安装activemq
1、把ActiveMQ 的压缩包上传到Linux系统
2、解压缩
tar -zxvf apache-activemq-5.12.0-bin.tar.gz -C /usr/java
2.3.启动和关闭
使用bin目录下的activemq命令:
启动:
[root@localhost bin]# ./activemq start
关闭:
[root@localhost bin]# ./activemq stop
查看状态:
[root@localhost bin]# ./activemq status
2.4.管理后台
进入管理后台:http://192.168.25.168:8161/admin
用户名:admin
密码:admin
主界面:
点对点消息列表:
发布订阅列表:
列表各列信息含义如下:
Number Of Pending Messages:等待消费的消息 这个是当前未出队列的数量。
Number Of Consumers:消费者 这个是消费者端的消费者数量
Messages Enqueued:进入队列的消息 进入队列的总数量,包括出队列的。
Messages Dequeued:出了队列的消息 可以理解为是消费者消费掉的数量。
4.应用ActiveMQ
依赖
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.13.4</version>
</dependency>
4.1.Queue
4.1.1.Producer
@Test
public void testQueueProducer() throws Exception {
// 第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
ConnectionFactory connectionFactory = new
ActiveMQConnectionFactory("tcp://192.168.204.150:61616");
// 第二步:使用ConnectionFactory对象创建一个Connection对象。
Connection connection = connectionFactory.createConnection();
// 第三步:开启连接,调用Connection对象的start方法。
connection.start();
// 第四步:创建session,(参数1:是否开启手动提交事务,参数2:消息确认模式)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 第五步:创建消息队列。
Queue queue = session.createQueue("test-queue");
// 第六步:使用Session对象创建一个Producer对象。
MessageProducer producer = session.createProducer(queue);
// 第七步:创建一个Message对象,创建一个TextMessage对象。
TextMessage textMessage = session.createTextMessage("hello,this is my queue msg.");
// 第八步:使用Producer对象发送消息。
producer.send(textMessage);
// 第九步:关闭资源。
producer.close();
session.close();
connection.close();
}
进入控制台查看:
4.1.2. Consumer
@Test
public void testQueueConsumer() throws Exception {
ConnectionFactory connectionFactory = new
ActiveMQConnectionFactory("tcp://192.168.25.168:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//发送端保持一致queue,并且队列的名称一致
Queue queue = session.createQueue("test-queue");
MessageConsumer consumer = session.createConsumer(queue);
//接收消息。
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
try {
TextMessage textMessage = (TextMessage) message;
String text = textMessage.getText();
// 第八步:打印消息。
System.out.println(text);
} catch (JMSException e) {
e.printStackTrace();
}
}
});
System.out.println("quque的消费者。。。。。");
//等待键盘输入
System.in.read();
// 第九步:关闭资源
consumer.close();
session.close();
connection.close();
}
4.2.Topic
注意:topic模式,必须先订阅,再发布,才能接受到消息,也就是说,必须先有消费者,在有生产者
4.2.1.Producer
@Test
public void testTopicProducer() throws Exception {
ConnectionFactory factory = new
ActiveMQConnectionFactory("tcp://192.168.190.128:61616");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("test-topic");
MessageProducer producer = session.createProducer(topic);
TextMessage textMessage = session.createTextMessage("hello,this is my topic msg");
producer.send(textMessage);;
producer.close();
session.close();
connection.close();
}
4.2.2.Consumer
ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.190.128:61616");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("test-topic");
MessageConsumer consumer = session.createConsumer(topic);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
TextMessage msg = (TextMessage) message;
try {
System.out.println(msg.getText());
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
System.out.println("topic的消费者。。。。。");
// 等待键盘输入
System.in.read();
consumer.close();
session.close();
connection.close();
同时开启2个以上的消费者,再次运行生产者,观察每个消费者控制台的输出,会发现每个消费者会接收到消息
5.Spring整合ActiveMQ
5.1.添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.3.22.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.13.4</version>
</dependency>
5.2.配置spring和Activemq整合
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd ">
<!-- 真正可以产生Connection的ConnectionFactory -->
<bean id="targetConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.190.128:61616" />
</bean>
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnectionFactory" />
</bean>
<!-- 配置生产者 -->
<!-- Spring提供的JMS工具类,它可以进行消息发送-->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<constructor-arg name="connectionFactory" ref="connectionFactory"/>
</bean>
<!--这个是队列目的地,点对点的 -->
<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg name="name" value="spring-queue" />
</bean>
<!--这个是主题目的地,一对多的 -->
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg name="name" value="spring-topic" />
</bean>
<!-- 接收消息 -->
<!-- 配置监听器 -->
<bean id="myMessageListener" class="com.usian.listener.MyMessageListener" />
<!-- 消息监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="queueDestination" />
<property name="messageListener" ref="myMessageListener" />
</bean>
5.3.测试 5.3.1.Producer
@Test
public void testQueueProducer() throws Exception {
// 第一步:初始化一个spring容器
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext-activemq.xml");
// 第二步:从容器中获得JMSTemplate对象。
JmsTemplate jmsTemplate = applicationContext.getBean(JmsTemplate.class);
// 第三步:从容器中获得一个Destination对象
Queue queue = (Queue) applicationContext.getBean("queueDestination");
// 第四步:使用JMSTemplate对象发送消息,需要知道Destination
jmsTemplate.send(queue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage textMessage = session.createTextMessage("spring activemq test");
return textMessage;
}
});
}
5.3.2.Consumer
创建消息监听者:
public class MyMessageListener implements MessageListener {
@Override
public void onMessage(Message message) {
try {
TextMessage textMessage = (TextMessage) message;
//取消息内容
String text = textMessage.getText();
System.out.println(text);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
创建测试类:
@Test
public void testQueueConsumer() throws Exception {
//初始化spring容器
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext-activemq.xml");
//等待
System.in.read();
}