AMQP介绍:
AMQP(advanced message queuing protocol)是一个提供统一消息服务的应用层标准协议,基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。(总结,一个应用层的数据传输协议)。
AMQP的定义:Wire-protocol。可跨语言,并提供了5种消息模型(direct、fanout、topic、headers、system)、由于是属于数据传输协议和跨语言的原因,因此只支持byte[](即二进制数据)。综合评价,AMPQ的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全
ActiveMQ介绍:
ActiveMQ是Apache出品,流行的、能力强劲的开源消息总线。ActiveMQ是一个完全支持的JMS1.1和J2EE1.4 规范的 JMS Provider 实现
ActiveMQ特性:
1、支持多语言(Java、C、C++、C#、Ruby、Perl、Python、PHP等)
2、支持多总应用协议(OpenWire、Stomp、REST、WS Notification、XMPP、AMQP)
3、完全支持JMS1.1和J2EE1.4规范(持久化、XA消息、事务)
4、虚拟主题、组合目的、镜像队列
ActiveMQ安装:
1.windows:
(1)、下载对应系统的安装包,并解压。
(2)、进入解压后的ActiveMQ根目录下的bin目录中,选择对应32或64位系统中。
(3)、(建议使用管理员方式运行)运行InstallService.bat文件进行服务安装(建议)或activemq.bat文件即可。(注:使用服务启动方式,在服务安装完成后需要在dos命令中输入net start ActiveMQ(服务名) 命令或直接在服务窗口中启动该服务,默认安装的服务名为ActiveMQ)
(4)、在浏览器中输入127.0.0.1:8161即可访问。(注:ActiveMQ:浏览器访问的默认端口号为8161,登陆账号与密码都为admin)
2.linux:
(1)、下载对应系统的安装包,并解压。
(2)、进入解压后的ActiveMQ根目录下的bin目录中
(3)、在终端中输入 ./activemq start 启动;./activemq stop 停止(注:具体访问windows安装(4)步骤)
JMS队列模式演示(p2p):
1.创建一个maven项目,并导包。
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.9.1</version>
</dependency>
1、示例1——生产者
package jms.activemq.queue;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 生产者
*/
public class AppProducers {
//连接路径,61616:为ActiveMQ默认端口
final static String url = "tcp://127.0.0.1:61616";
//创建的目标的队列名
final static String queueName = "queue-test";
public static void main(String[] args) throws JMSException {
//创建一个连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory(url);
//创建一个连接
Connection connection = factory.createConnection();
//启动连接
connection.start();
//创建一个会话,第一个参数表示是否在事务中处理(这里是不在事务中处理),第二个参数表示是应答模式(这里是自动应答)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建一个目标队列
Destination destination = session.createQueue(queueName);
//创建一个生产者,并指定消息的发送目标
MessageProducer producer = session.createProducer(destination);
//发送一百个消息给ActiveMQ
for(int i = 0; i<100; i++){
//创建一个消息
TextMessage message = session.createTextMessage("我就看看:"+i);
//发送消息
producer.send(message);
}
//用完之后,记得关闭连接噢!很重要的
connection.close();
}
}
运行结果:
2、示例2——消费者(注意:消费的是示例1发送的消息)
package jms.activemq.queue;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 消费者
*/
public class AppConsumer {
//连接路径,61616:为ActiveMQ默认端口
final static String url = "tcp://127.0.0.1:61616";
//创建的目标的队列名
final static String queueName = "queue-test";
public static void main(String[] args) throws Exception {
//创建一个连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory(url);
//创建一个连接
Connection connection = factory.createConnection();
//启动连接
connection.start();
//创建一个会话,第一个参数表示是否在事务中处理(这里是不在事务中处理),第二个参数表示是应答模式(这里是自动应答)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建一个目标队列
Destination destination = session.createQueue(queueName);
//创建一个消费者,并指定消息的发送目标
MessageConsumer consumer = session.createConsumer(destination);
//创建一个消息监听器,用以监听发送过来的消息
consumer.setMessageListener(new MessageListener() {
//接收消息时的处理方法
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage)message;
try {
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
//温馨提示:这里不能关闭连接噢,否者事件处理器无法监听消息,因此只能在关闭应用时才能关闭连接
}
}
JMS主题模式演示(注意:一定要先订阅者,在发布者,不然无法获取订阅之前发送到该主题的消息):
订阅者:
package jms.activemq.topic;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 订阅者
*/
public class AppConsumer {
//连接路径,61616:为ActiveMQ默认端口
final static String url = "tcp://127.0.0.1:61616";
//创建的目标的主题名
final static String topicName = "topic-test";
public static void main(String[] args) throws Exception {
//创建一个连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory(url);
//创建一个连接
Connection connection = factory.createConnection();
//启动连接
connection.start();
//创建一个会话,第一个参数表示是否在事务中处理(这里是不在事务中处理),第二个参数表示是应答模式(这里是自动应答)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建一个目标主题
Destination destination = session.createTopic(topicName);
//创建一个订阅者,并指定消息的发送目标
MessageConsumer consumer = session.createConsumer(destination);
//创建一个消息监听器,用以监听发送过来的消息
consumer.setMessageListener(new MessageListener() {
//接收消息时的处理方法
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage)message;
try {
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
//温馨提示:这里不能关闭连接噢,否者事件处理器无法监听消息,因此只能在关闭应用时才能关闭连接
}
}
发布者:
package jms.activemq.topic;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 发布者
*/
public class AppProducers {
//连接路径,61616:为ActiveMQ默认端口
final static String url = "tcp://127.0.0.1:61616";
//创建的目标的主题名
final static String topicName = "topic-test";
public static void main(String[] args) throws JMSException {
//创建一个连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory(url);
//创建一个连接
Connection connection = factory.createConnection();
//启动连接
connection.start();
//创建一个会话,第一个参数表示是否在事务中处理(这里是不在事务中处理),第二个参数表示是应答模式(这里是自动应答)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建一个目标主题
Destination destination = session.createTopic(topicName);
//创建一个发布者,并指定消息的发送目标
MessageProducer producer = session.createProducer(destination);
//发送一百个消息给ActiveMQ
for(int i = 0; i<100; i++){
//创建一个消息
TextMessage message = session.createTextMessage("我就看看:"+i);
//发送消息
producer.send(message);
System.out.println(message.getText());
}
//用完之后,记得关闭连接噢!很重要的
connection.close();
}
}
Spring集成JMS——队列示例:
生产者:
1、使用在Spring配置文件中将ActiveMQ加入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"
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">
<!-- 激活在spring容器中注册过的bean -->
<context:annotation-config/>
<!-- ActiveMQ提供的ConnertionFactory -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://127.0.0.1:61616"></property>
</bean>
<!-- Spring jms提供的提供的连接池 -->
<bean id="connertionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
</bean>
<!-- 一个队列目的地,点对点的 -->
<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
<!-- 构造注入,spring-queue目的地名 -->
<constructor-arg value="spring-queue"/>
</bean>
</beans>
2、开始配置生产者独有的配置:
<?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">
<!-- 引入一段公共的配置 -->
<import resource="common.xml"/>
<!-- 使用spring提供的消息发送模板 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 为该模板绑定连接 -->
<property name="connectionFactory" ref="connertionFactory"></property>
</bean>
<!-- 将ProducerServiceImpl填入Spring容器中进行管理 -->
<bean class="spring.jms.queue.producer.ProducerSrviceImpl"></bean>
</beans>
3、创建上述配置文件中的生产者发送消息接口及实现类(ProducerSrviceImpl)。
package spring.jms.queue.producer;
public interface ProducerService {
void sendMessage(String message);
}
package spring.jms.queue.producer;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
public class ProducerSrviceImpl implements ProducerService {
@Autowired
JmsTemplate jmsTemplate;
@Autowired
@Qualifier("queueDestination")//将队列目标注入进来,因为可以创建多个,所以使用byName注入
Destination destination;
public void sendMessage(final String message) {
//使用jmsTemplate模板发送消息
jmsTemplate.send(destination,new MessageCreator() {
//创建一个消息
public Message createMessage(Session session) throws JMSException {
TextMessage textMessage = session.createTextMessage(message);
System.out.println("发送消息:"+textMessage.getText());
return textMessage;
}
});
}
}
4、创建生产者的启动类:
package spring.jms.queue.producer;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*生产者——队列——启动类
*/
public class AppProducer {
public static void main(String[] args){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:queue/producer.xml");
ProducerService producerService = ac.getBean(ProducerService.class);
for(int i = 0;i < 100;i++ ){
producerService.sendMessage("test-spring-jms: "+i);
}
ac.close();
}
}
消费者:
1、将ActiveMQ加入到Spring容器中进行配置(这里引入了一段公共的配置,上面提到了的common.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">
<!-- 引入一段公共的配置 -->
<import resource="common.xml"/>
<!-- 配置消息监听器 -->
<bean id="consumerMessageListener" class="spring.jms.queue.consumer.ConsumerMessageListener"/>
<!-- 配置消息容器,需要指定连接,目标,监听器等 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connertionFactory"></property>
<property name="destination" ref="queueDestination"></property>
<property name="messageListener" ref="consumerMessageListener"></property>
</bean>
</beans>
2、创建上述配置文件中的消息监听器(需要实现MessageListener接口)
package spring.jms.queue.consumer;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
/**
* 创建一个消息监听者,需要实现MessageListener接口
*/
public class ConsumerMessageListener implements MessageListener {
//处理监听到的消息的方法
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage)message;
try {
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
3、创建消费者启动类:
package spring.jms.queue.consumer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*消费者——队列——启动类
*/
public class AppConsumer {
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:queue/consumer.xml");
}
}
Spring集成JMS——主题示例(与上述Spring集成JMS——队列模式类似):
发布者:
1.同上,创建一段公共的配置,并配置发布者独有的配置。
<?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">
<!-- 激活在spring容器中注册过的bean -->
<context:annotation-config/>
<!-- ActiveMQ提供的ConnertionFactory -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://127.0.0.1:61616"></property>
</bean>
<!-- Spring jms提供的提供的连接池 -->
<bean id="connertionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
</bean>
<!-- 一个队列目的地,点对点的 -->
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<!-- 构造注入,spring-queue目的地名 -->
<constructor-arg value="spring-topic"/>
</bean>
</beans>
<?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">
<!-- 引入一段公共的配置 -->
<import resource="common.xml"/>
<!-- 使用spring提供的消息发送模板 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 为该模板绑定连接 -->
<property name="connectionFactory" ref="connertionFactory"></property>
</bean>
<!-- 将ProducerServiceImpl填入Spring容器中进行管理 -->
<bean class="spring.jms.topic.producer.ProducerSrviceImpl"></bean>
</beans>
2、创建上述配置文件中的发布者发送消息的接口及实现类:
package spring.jms.topic.producer;
public interface ProducerService {
void sendMessage(String message);
}
package spring.jms.topic.producer;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
public class ProducerSrviceImpl implements ProducerService {
@Autowired
JmsTemplate jmsTemplate;
@Autowired
@Qualifier("topicDestination")//将主题目标注入进来,因为可以创建多个,所以使用byName注入
Destination destination;
public void sendMessage(final String message) {
//使用jmsTemplate模板发送消息
jmsTemplate.send(destination,new MessageCreator() {
//创建一个消息
public Message createMessage(Session session) throws JMSException {
TextMessage textMessage = session.createTextMessage(message);
System.out.println("发送消息:"+textMessage.getText());
return textMessage;
}
});
}
}
3、创建移动类:
package spring.jms.topic.producer;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*发布者——主题——启动类
*/
public class AppProducer {
public static void main(String[] args){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:topic/producer.xml");
ProducerService producerService = ac.getBean(ProducerService.class);
for(int i = 0;i < 100;i++ ){
producerService.sendMessage("test-spring-jms: "+i);
}
ac.close();
}
}
订阅者:
1、将ActiveMQ加载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"
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">
<!-- 引入一段公共的配置 -->
<import resource="common.xml"/>
<!-- 配置消息监听器 -->
<bean id="consumerMessageListener" class="spring.jms.queue.consumer.ConsumerMessageListener"/>
<!-- 配置消息容器,需要指定连接,目标,监听器等 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connertionFactory"></property>
<property name="destination" ref="topicDestination"></property>
<property name="messageListener" ref="consumerMessageListener"></property>
</bean>
</beans>
2、创建上述配置文件中的消息监听器(MessageListener):
package spring.jms.topic.consumer;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
/**
* 创建一个消息监听者,需要实现MessageListener接口
*/
public class ConsumerMessageListener implements MessageListener {
//处理监听到的消息的方法
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage)message;
try {
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
3、创建订阅者启动类:
package spring.jms.topic.consumer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*订阅者——主题——启动类
*/
public class AppConsumer {
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:topic/consumer.xml");
}
}