简介
1.什么是消息中间件
消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进 程间的通信。对于消息中间件,常见的角色大致也就有 Producer(生产者)、Consumer(消 费者)
2.常见的消息中间件
(1)**ActiveMQ**
ActiveMQ 是 Apache 出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完 全支持 JMS1.1 和 J2EE 1.4 规范的 JMS Provider 实现。
(2)RabbitMQ
AMQP 协议的领导实现,支持多种场景。淘宝的 MySQL 集群内部有使用它进行通讯, OpenStack 开源云平台的通信组件,最先在金融行业得到运用。
(3)ZeroMQ
史上最快的消息队列系统
(4)Kafka
Apache 下的一个子项目 。特点:高吞吐,在一台普通的服务器上既可以达到 10W/s 的吞吐速率;完全的分布式系统。适合处理海量数据。
JMS
1 简介
JMS(Java Messaging Service)是 Java 平台上有关面向消息中间件的技术规范,它便 于消息系统中的 Java 应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的 接口简化企业应用的开发。
JMS 本身只定义了一系列的接口规范,是一种与厂商无关的 API,用来访问消息收发系 统。它类似于 JDBC(java Database Connectivity):这里,JDBC 是可以用来访问许多不同关 系数据库的 API,而 JMS 则提供同样与厂商无关的访问方法,以访问消息收发服务。
许多厂商目前都支持 JMS,包括 IBM 的 MQSeries、BEA 的 Weblogic JMS service 和 Progress 的 SonicMQ,这只是几个例子。 JMS 使您能够通过消息收发服务(有时称为消息中介程序或 路由器)从一个 JMS 客户机向另一个 JML 客户机发送消息。消息是 JMS 中的一种类型对 象,由两部分组成:报头和消息主体。
报头 由路由信息以及有关该消息的元数据组成。
消息 主体则携带着应用程序的数据或有效负载
2 消息正文格式:
· TextMessage—一个字符串对象
· MapMessage—一套名称-值对
· ObjectMessage—一个序列化的 Java 对象
· BytesMessage—一个字节的数据流
· StreamMessage **— Java 原始值的数据流
3 消息传递类型
点对点消息类型下,如果没有消费者,队列会将消息存储,在消费者连接的时候将消息发送给消费者.如果由两个或以上的消费者监听同一个队列,使用轮询的模式进行消息处理
发布模式类型下,不管有没有消费者监听,容器都会将消息发布出去,有多少个消费者就会由多少个消费者接收到消息.
**一种是点对点的,即一个消息只能由一个消费者消费; 
另一种是发布/ 订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。 
ActiveMQ
1.下载
官方网站下载:http://activemq.apache.org/
2.安装(Linux) 和启动
**(1)将 下载好的apache-activemq-5.12.0-bin.tar.gz 上传至服务器
(2)解压此文件
tar zxvf apache-activemq-5.12.0-bin.tar.gz
(3)为 apache-activemq-5.12.0 目录赋权
chmod 777 apache-activemq-5.12.0
(4)进入 apache-activemq-5.12.0\bin 目录
(5)赋与执行权限
chmod 755 activemq
(6) 启动
./activemq start
启动成功:
访问管理页面
http://ip:8161/ 进入中管理页面
登陆:
默认用户名和密码
admin,admin
各列的含义:
Number Of Pending Messages :等待消费的消息 这个是当前未出队列的数量。
Number Of Consumers :消费者 这个是消费者端的消费者数量
Messages Enqueued :进入队列的消息 进入队列的总数量,包括出队列的。
Messages Dequeued :出了队列的消息 可以理解为是消费这消费掉的数量
入门Demo
准备:
引入依赖
<dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-client</artifactId><version>5.13.4</version></dependency>
Queue
1.创建queue消息生产对象
public class QueueProducer {public static void main(String[] args) throws JMSException {//1.创建连接工厂ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.128:61616");//2.获取连接Connection connection = connectionFactory.createConnection();//3.启动连接connection.start();//4.获取 session (参数 1:是否启动事务,参数 2:消息确认模式)Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);//5.创建队列对象Queue queue = session.createQueue("test-queue");//6.创建消息生产者MessageProducer producer = session.createProducer(queue);//7.创建消息TextMessage textMessage = session.createTextMessage("欢迎使用消息中间件");//8.发送消息producer.send(textMessage);//9.关闭资源producer.close();session.close();connection.close();}}
第四步中参数的类型
2.创建queue消息消费者
//1.创建连接工厂ConnectionFactory connectionFactory=newActiveMQConnectionFactory("tcp://192.168.25.135:61616");//2.获取连接Connection connection = connectionFactory.createConnection();//3.启动连接connection.start();//4.获取 session (参数 1:是否启动事务,参数 2:消息确认模式)Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);//5.创建队列对象Queue queue = session.createQueue("test-queue");//6.创建消息消费MessageConsumer consumer = session.createConsumer(queue);//7.监听消息consumer.setMessageListener(new MessageListener() {public void onMessage(Message message) {TextMessage textMessage=(TextMessage)message;try {System.out.println("接收到消息:"+textMessage.getText());} catch (JMSException e) {// TODO Auto-generated catch blocke.printStackTrace();}}});//8.等待键盘输入System.in.read();//9.关闭资源consumer.close();session.close();connection.close();
3.运行结果

Topic
1.创建topic生产者
public class TopicProducer {public static void main(String[] args) throws JMSException {//1.创建连接工厂ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.135:61616");//2.获取连接Connection connection = connectionFactory.createConnection();//3.启动连接connection.start();//4.获取 session (参数 1:是否启动事务,参数 2:消息确认模式)Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);//5.创建主题对象Topic topic = session.createTopic("test-topic");//6.创建消息生产者MessageProducer producer = session.createProducer(topic);//7.创建消息TextMessage textMessage = session.createTextMessage("欢迎使用消息中间件服务");//8.发送消息producer.send(textMessage);//9.关闭资源producer.close();session.close();connection.close();}}
2创建topic消费者
public class TopicConsumer {public static void main(String[] args) throws JMSException, IOException {//1.创建连接工厂ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.135:61616");//2.获取连接Connection connection = connectionFactory.createConnection();//3.启动连接connection.start();//4.获取 session (参数 1:是否启动事务,参数 2:消息确认模式)Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);//5.创建主题对象//Queue queue = session.createQueue("test-queue");Topic topic = session.createTopic("test-topic");//6.创建消息消费MessageConsumer consumer = session.createConsumer(topic);//7.监听消息consumer.setMessageListener(new MessageListener() {public void onMessage(Message message) {TextMessage textMessage = (TextMessage) message;try {System.out.println("接收到消息:" + textMessage.getText());} catch (JMSException e) {// TODO Auto-generated catch blocke.printStackTrace();}}});//8.等待键盘输入System.in.read();//9.关闭资源consumer.close();session.close();connection.close();}}
运行结果:


注意:
需要先启动消费者才会收到消息
spring整合消息中间件
1.准备
创建两个maven项目,同时导入依赖坐标

<properties><spring.version>4.2.4.RELEASE</spring.version></properties><!-- jms --><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-jms</artifactId><version>${spring.version}</version></dependency><!-- 测试 --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.9</version></dependency><!-- activate mq --><dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-client</artifactId><version>5.13.4</version></dependency></dependencies>
2.Queue生产者项目
2.1resources/spring/applicationContext-jms-producer.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 注解扫描 --><context:component-scan base-package="com.moonhu.demo"></context:component-scan><!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供--><bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"><property name="brokerURL" value="tcp://192.168.25.128:61616"/></bean><!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --><bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"><!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory --><property name="targetConnectionFactory" ref="targetConnectionFactory"/></bean><!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 --><bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"><!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 --><property name="connectionFactory" ref="connectionFactory"/></bean><!--1.这个是队列目的地,点对点的 文本信息--><bean id="queueTextDestination" class="org.apache.activemq.command.ActiveMQQueue"><!-- 队列名称 --><constructor-arg value="queue_text"/></bean><!--2.这个是订阅模式 文本信息--><bean id="topicTextDestination" class="org.apache.activemq.command.ActiveMQTopic"><constructor-arg value="topic_text"/></bean></beans>
2.2QueueDemo

@Componentpublic class QueueDemo {/*** 模板*/@Autowiredprivate JmsTemplate jmsTemplate;/*** 容器*/@Autowiredprivate Destination queueTextDestination;/*** 发送文本消息** @param text*/public void sendTextMessage(final String text) {// 发送消息jmsTemplate.send(queueTextDestination, new MessageCreator() {public Message createMessage(Session session) throws JMSException {// 创建文本信息return session.createTextMessage(text);}});}}
2.3测试方法

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:spring/applicationContext-jms-producer.xml")public class QueueTest {@Autowiredprivate QueueDemo queueDemo;@Testpublic void testSend() {queueDemo.sendTextMessage("SpringJms-点对点");}}
3.Queue消费者项目
3.1resources/spring/applicationContext-jms-consumer.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供--><bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"><property name="brokerURL" value="tcp://192.168.25.128:61616"/></bean><!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --><bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"><!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory --><property name="targetConnectionFactory" ref="targetConnectionFactory"/></bean><!--这个是队列目的地,点对点的 文本信息--><bean id="queueTextDestination" class="org.apache.activemq.command.ActiveMQQueue"><constructor-arg value="queue_text"/></bean><!-- 我的监听类 --><bean id="queueListener" class="com.moonhu.demo.QueueListener"/><!-- 消息监听容器 --><bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"><property name="connectionFactory" ref="connectionFactory"/><property name="destination" ref="queueTextDestination"/><property name="messageListener" ref="queueListener"/></bean></beans>
3.2QueueListener

public class QueueListener implements MessageListener {/*** MessageListener接口的抽象方法** @param message 接收的数据*/public void onMessage(Message message) {// 数据强转TextMessage textMessage = (TextMessage) message;try {// 获取数据并输出System.out.println("接收到消息:" + textMessage.getText());} catch (JMSException e) {e.printStackTrace();}}}
3.3测试类

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:/spring/applicationContext-jms-consumer.xml")public class QueueTest {/*** Queue消费者测试方法*/@Testpublic void testReceive() {try {// 只需要使程序不结束监听数据即可System.in.read();} catch (IOException e) {e.printStackTrace();}}}
3.4测试结果

4.Topic生产者
4.1resources/spring/applicationContext-jms-producer.xml
需要有Topic的ActiveMQTopicbean对象
<!--2.这个是订阅模式 文本信息--><bean id="topicTextDestination" class="org.apache.activemq.command.ActiveMQTopic"><constructor-arg value="topic_text"/></bean>
4.2TopicDemo

@Componentpublic class TopicDemo {@Autowiredprivate JmsTemplate jmsTemplate;@Autowiredprivate Destination topicTextDestination;/*** 发送文本消息** @param text*/public void sendTextMessage(final String text) {jmsTemplate.send(topicTextDestination, new MessageCreator() {public Message createMessage(Session session) throws JMSException {return session.createTextMessage(text);}});}}
4.3测试方法

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:spring/applicationContext-jms-producer.xml")public class TopicTest {@Autowiredprivate TopicDemo topicDemo;/*** Topic发送消息测试*/@Testpublic void testSend(){// 发送消息topicDemo.sendTextMessage("Topic-send-test");}}
5.Topic消费者
5.1resources/spring/applicationContext-jms-consumer.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供--><bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"><property name="brokerURL" value="tcp://192.168.25.128:61616"/></bean><!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --><bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"><!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory --><property name="targetConnectionFactory" ref="targetConnectionFactory"/></bean><!-- 队列方法开始 --><!--这个是队列目的地,点对点的 文本信息--><bean id="queueTextDestination" class="org.apache.activemq.command.ActiveMQQueue"><constructor-arg value="queue_text"/></bean><!-- 我的监听类 --><bean id="queueListener" class="com.moonhu.demo.QueueListener"/><!-- 消息监听容器 --><bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"><property name="connectionFactory" ref="connectionFactory"/><property name="destination" ref="queueTextDestination"/><property name="messageListener" ref="queueListener"/></bean><!-- 队列方法结束 --><!-- 发布的方法开始 --><!--这个是队列目的地,点对点的 文本信息--><bean id="topicTextDestination" class="org.apache.activemq.command.ActiveMQTopic"><constructor-arg value="queue_text"/></bean><!-- 我的监听类 --><bean id="topicListener" class="com.moonhu.demo.TopicListener"/><!-- 消息监听容器 --><bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"><property name="connectionFactory" ref="connectionFactory"/><property name="destination" ref="topicTextDestination"/><property name="messageListener" ref="topicListener"/></bean><!-- 发布的方法结束 --></beans>
5.2TopicListener

/*** Topic消费者的监听类*/public class TopicListener implements MessageListener {public void onMessage(Message message) {TextMessage textMessage = (TextMessage) message;try {System.out.println("接收到的消息: " + textMessage.getText());} catch (JMSException e) {e.printStackTrace();}}}
5.3测试方法

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:spring/applicationContext-jms-consumer.xml")public class TopicTest {@Testpublic void testReceive() {try {System.in.read();} catch (IOException e) {e.printStackTrace();}}}
5.4测试结果

6.SpringBoot整合ActivateMQ
6.1. 引入相关依赖:

<properties><!-- 指定java版本 --><java.version>1.7</java.version></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.4.0.RELEASE</version></parent><dependencies><!-- springBoot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 热部署 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><!-- 整合activateMQ --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-activemq</artifactId></dependency></dependencies>
6.2. 创建引导类

import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/**** 引导类*/@SpringBootApplicationpublic class SpringBootDemo {public static void main(String[] args) {SpringApplication.run(SpringBootDemo.class, args);}}
6.3创建控制类
@RestControllerpublic class HelloWordTest {@Autowiredprivate JmsMessagingTemplate jmsMessagingTemplate;/*** activate发消息测试*/@RequestMapping("/sendMsg")public void sendMessage() {jmsMessagingTemplate.convertAndSend("boot", "hello,你好");}}
6.4创建消费者类
创建消费者1
/*** 监听器*/@Componentpublic class ConsumeDemo1 {/*** 接收消息** @param msg*/@JmsListener(destination = "boot")public void getMessage(String msg) {System.out.println(msg+1);}}
创建消费者2
/*** 监听器*/@Componentpublic class ConsumeDemo2 {/*** 接收消息** @param msg*/@JmsListener(destination = "boot")public void getMessage(String msg) {System.out.println(msg+2);}}
6.5启动引导类

6.6 访问地址查看结果
http://localhost:8080/sendMsg
多次访问后输出结果
解析:
在spring的spring-boot-starter-activemq的依赖中,传递依赖了ActivateMQ的包不需要连接远端的ActivateMq服务器即可实现消息的发送和接收,使用的是内置的服务.发送的是Queue消息
如果要使用自己部署的服务器需要在配置文件中指定ActivateMQ的地址
spring.activemq.broker-url=tcp://192.168.25.128:61616
注意:
key值不能改变
思考
消费者接收不到消息
1.生产者和消费者桶名称不同
