1.1. 什么是ActiveMQ
ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ是一个完全支持JMS1.1和J2EE 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. ActiveMQ的消息形式
对于消息的传递有两种类型:
一种是点对点的,即一个生产者和一个消费者一一对应;
另一种是发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。
JMS定义了五种不同的消息正文格式,以及调用的消息类型,允许你发送并接收以一些不同形式的数据,提供现有消息格式的一些级别的兼容性。
· StreamMessage -- Java原始值的数据流
· MapMessage--一套名称-值对
· TextMessage--一个字符串对象
· ObjectMessage--一个序列化的Java对象
· BytesMessage--一个字节的数据流
1.3. ActiveMQ的安装(Linux)
我使用的版本是5.12.0,先分享下:apache-activemq-5.12.0-bin.tar.gz
解压后我们先看看它的目录结构(重要目录):
activemq-all-5.12.0.jar这个是activemq的客户端
.你需要是用这个客户端则加入到你工程中去
.如果你使用spring跟activemq整合的话,不推荐使用activemq-all-5.12.0.jar
( 因为这个jar包里包含spring的包结构,那么两者将会发生冲突)bin目录下是一些启动MQ的脚本文件
conf目录下是MQ的配置文件,基本不需要动
data目录下是服务端的缓存数据
docs目录下是文档
lib目录下是所有依赖的jar包
webapps目录是管理后台文件
1.4. ActiveMQ的启动
进入bin目录下输入 ./activemq start 命令启动activemq
查看是否成功启动activemq:
输入命令查看进程:ps aux|grep activemq
浏览器登录后台:ip地址:8161/admin/ (例如:192.168.25.117:8161/admin) 用户名和密码都是admin
如果在访问过程中出现了503错误的话,一般是你的地址没有映射机器名
解决方法:
1、查看机器名
[root@iz2zea1ofhnvummd9pzg2wz ~]# cat /etc/sysconfig/network
# Created by anaconda
NETWORKING_IPV6=no
PEERNTP=no
GATEWAY=(涉及隐私,就删了)
HOSTNAME=iZ2zea1ofhnvummd9pzg2wZ
2、修改hosts文件
[root@iz2zea1ofhnvummd9pzg2wz ~]# cat /etc/hosts
127.0.0.1 localhost
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
(这里加上前面我删了的) iZ2zea1ofhnvummd9pzg2wZ
3、重启Activemq服务
1.5. ActiveMQ发送queue消息
@Test
/**
* 测试activemq
* queue
*/
public void testActiveMQ() throws Exception{
//1.创建一个连接工厂对象connectionFactory对象服务的ip和端口
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("tcp://192.168.25.168:61616");
//2.使用connectionFactory创建连接connection对象
Connection connection=connectionFactory.createConnection();
//3.开启连接。调用Connection对象的start方法
connection.start();
//4.使用Connection创建一个Session对象
//第一个参数是开否开启事物,一般不使用事物,保证数据的最终一致性,可以使用消息队列来实现
//如果第一个参数伟true那么第二个参数自动忽略,如果不开启事物false,第二个参数为消息的应答模式,一般自动应答就可以
Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.使用session对象创建一个Destination对象,两种形式queue、topic,目前使用queue
Queue queue =session.createQueue("test-queue");//参数就是消息队列的名称
//6.使用session对象创建一个prodicer对象
MessageProducer messageProducer=session.createProducer(queue);
//7.创建一个textMessage对象
/*TextMessage textMessage=new ActiveMQTextMessage();
textMessage.setText("hello activeMQ");*/
//或者直接用session
TextMessage message=session.createTextMessage("hello activeMQ");
//8.发送消息
messageProducer.send(message);
//9.关闭资源
messageProducer.close();
session.close();
connection.close();
}
1.6. ActiveMQ接收queue消息
/**
* QueueConsumer消息消费者
*/
@Test
public void testQueueConsumer()throws Exception{
//创建一个连接工厂对象
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("tcp://192.168.25.168:61616");
//使用连接工厂对象创建一个连接
Connection connection=connectionFactory.createConnection();
//开启连接
connection.start();
//使用连接对象创建一个session对象
Session session=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//使用session对象创建一个Destination对象
Queue queue =session.createQueue("test-queue");
//使用Session创建一个Consumer对象
MessageConsumer consumer= session.createConsumer(queue);
//向Consumer对象中设置一个MessageListener对象,用来接收消息
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
//取消息的内容
if(message instanceof TextMessage){
TextMessage textMessage=(TextMessage) message;
try {
String text=textMessage.getText();
//打印消息内容
System.out.println(text);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
//系统等待接收消息
/*while (true) {
Thread.sleep(100);
}*/
System.in.read();
//关闭资源
consumer.close();
session.close();
connection.close();
}
1.7. topic
/**
* topic
* @throws Exception
*/
@Test
public void testTopicProducer() throws Exception {
// 第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
// brokerURL服务器的ip及端口号
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.168:61616");
// 第二步:使用ConnectionFactory对象创建一个Connection对象。
Connection connection = connectionFactory.createConnection();
// 第三步:开启连接,调用Connection对象的start方法。
connection.start();
// 第四步:使用Connection对象创建一个Session对象。
// 第一个参数:是否开启事务。true:开启事务,第二个参数忽略。
// 第二个参数:当第一个参数为false时,才有意义。消息的应答模式。1、自动应答2、手动应答。一般是自动应答。
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个topic对象。
// 参数:话题的名称。
Topic topic = session.createTopic("test-topic");
// 第六步:使用Session对象创建一个Producer对象。
MessageProducer producer = session.createProducer(topic);
// 第七步:创建一个Message对象,创建一个TextMessage对象。
/*
* TextMessage message = new ActiveMQTextMessage(); message.setText(
* "hello activeMq,this is my first test.");
*/
TextMessage textMessage = session.createTextMessage("hello activeMq,this is my topic test");
// 第八步:使用Producer对象发送消息。
producer.send(textMessage);
// 第九步:关闭资源。
producer.close();
session.close();
connection.close();
}
/**
* 订阅者
* @throws Exception
*/
@Test
public void testTopicConsumer() throws Exception {
// 第一步:创建一个ConnectionFactory对象。
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.168:61616");
// 第二步:从ConnectionFactory对象中获得一个Connection对象。
Connection connection = connectionFactory.createConnection();
// 第三步:开启连接。调用Connection对象的start方法。
connection.start();
// 第四步:使用Connection对象创建一个Session对象。
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 第五步:使用Session对象创建一个Destination对象。和发送端保持一致topic,并且话题的名称一致。
Topic topic = session.createTopic("test-topic");
// 第六步:使用Session对象创建一个Consumer对象。
MessageConsumer consumer = session.createConsumer(topic);
// 第七步:接收消息。
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
try {
TextMessage textMessage = (TextMessage) message;
String text = null;
// 取消息的内容
text = textMessage.getText();
// 第八步:打印消息。
System.out.println(text);
} catch (JMSException e) {
e.printStackTrace();
}
}
});
System.out.println("topic的消费端02。。。。。");
// 等待键盘输入
System.in.read();
// 第九步:关闭资源
consumer.close();
session.close();
connection.close();
}
1.8. spring整合activemq发送消息
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
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-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 指定JMS的服务厂商提供的ConnectionFactory -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg name="brokerURL" value="tcp://192.168.25.168:61616"/>
</bean>
<!--Spring对ConnectionFactory对象的封装 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnectionFactory"></property>
</bean>
<!-- 配置jmsTemplate -->
<bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>
<!--配置消息的Destination对象 -->
<bean id="test-queue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg name="name" value="test-queue"></constructor-arg>
</bean>
<bean id="test-topic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg name="name" value="test-topic"></constructor-arg>
</bean>
</beans>
java调用代码
/**
* 使用jmsTempla发送消息
*/
@Test
public void testJmsTemplate() throws Exception{
//初始化Spring容器
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:spring/applicationContext-ActiverMq.xml");
//从容器中取得JmsTemplate对象
JmsTemplate jmsTemplate=applicationContext.getBean(JmsTemplate.class);
//从容器中获得destination对象
Destination destination=(Destination) applicationContext.getBean("test-queue");
//发送消息
jmsTemplate.send(destination,new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
TextMessage textMessage=session.createTextMessage("the is my no.1 springQueue");
return textMessage;
}
});
}
1.8. spring整合activemq接收消息<!-- 配置消息的接收者 -->
<bean id="myMessageListener" class="com.service.MyMessageListener"/>
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<!-- 引用连接工厂 -->
<property name="connectionFactory" ref="connectionFactory"></property>
<!-- 调用一对多 -->
<property name="destination" ref="test-queue"></property>
<!-- 调用消息的接收者 -->
<property name="messageListener" ref="myMessageListener"></property>
</bean>
package com.service;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
/**
* 接收ActiveMq发送的消息
* @author Administrator
*
*/
public class MyMessageListener implements MessageListener {
public void onMessage(Message message) {
//接收消息
TextMessage textMessage=(TextMessage) message;
try {
String test=textMessage.getText();
System.out.println(test);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
/**
* springAvtivemq接收消息
* @throws Exception
*/
@Test
public void testSpirngActiveMQ() throws Exception{
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:spring/applicationContext-ActiverMq.xml");
System.in.read();
}
<!-- 配置消息的接收者 -->
<bean id="myMessageListener" class="com.service.MyMessageListener"/>
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<!-- 引用连接工厂 -->
<property name="connectionFactory" ref="connectionFactory"></property>
<!-- 调用一对多 -->
<property name="destination" ref="test-queue"></property>
<!-- 调用消息的接收者 -->
<property name="messageListener" ref="myMessageListener"></property>
</bean>
package com.service;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
/**
* 接收ActiveMq发送的消息
* @author Administrator
*
*/
public class MyMessageListener implements MessageListener {
public void onMessage(Message message) {
//接收消息
TextMessage textMessage=(TextMessage) message;
try {
String test=textMessage.getText();
System.out.println(test);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
/**
* springAvtivemq接收消息
* @throws Exception
*/
@Test
public void testSpirngActiveMQ() throws Exception{
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:spring/applicationContext-ActiverMq.xml");
System.in.read();
}