一、ActiveMQ安裝
1.windows安裝
首先去http://activemq.apache.org/download.html 下載最新版本
目錄如下:
+bin (windows下面的bat和unix/linux下面的sh)
+conf (activeMQ配置目錄,包含最基本的activeMQ配置文件)
+data (默認是空的)
+docs (index,replease版本里面沒有文檔,-.-b不知道爲啥不帶)
+example (幾個例子)
+lib (activemMQ使用到的lib)
-apache-activemq-4.1-incubator.jar (ActiveMQ的binary)
-LICENSE.txt
運行信息
運行信息
-NOTICE.txt
-README.txt
-user-guide.html
啓動bin/win64/activemq.bat
啓動成功就可以訪問管理員界面:http://localhost:8161/admin
默認用戶名和密碼admin/admin。如果你想修改用戶名和密碼的話,在conf/jetty-realm.properties中修改即可。
2.Linux安裝
wget http://archive.apache.org/dist/activemq/5.14.1/apache-activemq-5.14.1-bin.tar.gz
cd apache-activemq-5.14.1/bin/linux-x86-64/
./activemq start
二、ActiveMQ應用
1.點對點方式(point to point Queue)
點對點的消息發送方式主要建立在 Message Queue,Sender,reciever上,Message Queue 存貯消息,Sneder 發送消息,receive接收消息.具體點就是Sender Client發送Message Queue ,而 receiver Cliernt從Queue中接收消息和”發送消息已接受”到Quere,確認消息接收。消息發送客戶端與接收客戶端沒有時間上的依賴,發送客戶端可以在任何時刻發送信息到Queue,而不需要知道接收客戶端是不是在運行
2.發佈/訂閱方式(public/subscriber Messaging Topic)
發佈/訂閱方式用於多接收客戶端的方式.作爲發佈訂閱的方式,可能存在多個接收客戶端,並且接收端客戶端與發送客戶端存在時間上的依賴。一個接收端只能接收他創建以後發送客戶端發送的信息。作爲subscriber ,在接收消息時有兩種方法,destination的receive方法,和實現message listener 接口的onMessage 方法。
發送消息的基本步驟:
- 創建連接使用的工廠類JMS ConnectionFactory
- 使用管理對象JMS ConnectionFactory建立連接Connection,並啓動
- 使用連接Connection 建立會話Session
- 使用會話Session和管理對象Destination創建消息生產者MessageSender
- 使用消息生產者MessageSender發送消息
消息接收者從JMS接受消息的步驟 :
- 創建連接使用的工廠類JMS ConnectionFactory
- 使用管理對象JMS ConnectionFactory建立連接Connection,並啓動
- 使用連接Connection 建立會話Session
- 使用會話Session和管理對象Destination創建消息接收者MessageReceiver
- 使用消息接收者MessageReceiver接受消息,需要用setMessageListener將MessageListener接口綁定到MessageReceiver消息接收者必須實現了MessageListener接口,需要定義onMessage事件方法。
3.JMS方式
接受者
public class MessageReceiver {
// tcp 地址
public static final String BROKER_URL = "tcp://localhost:61616";
// 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
public static final String DESTINATION = "hoo.mq.queue";
public static void run() throws Exception {
Connection connection = null;
Session session = null;
try {
// 創建鏈接工廠
ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
// 通過工廠創建一個連接
connection = factory.createConnection();
// 啓動連接
connection.start();
// 創建一個session會話
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 創建一個消息隊列
Destination destination = session.createQueue(DESTINATION);
// 創建消息製作者
MessageConsumer consumer = session.createConsumer(destination);
while (true) {
// 接收數據的時間(等待) 100 ms
Message message = consumer.receive(1000 * 100);
TextMessage text = (TextMessage) message;
if (text != null) {
System.out.println("接收:" + text.getText());
} else {
break;
}
}
// 提交會話
session.commit();
} catch (Exception e) {
throw e;
} finally {
// 關閉釋放資源
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
public static void main(String[] args) throws Exception {
MessageReceiver.run();
}
}
發送者
public class MessageSender {
// 發送次數
public static final int SEND_NUM = 5;
// tcp 地址
public static final String BROKER_URL = "tcp://localhost:61616";
// 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
public static final String DESTINATION = "hoo.mq.queue";
@SuppressWarnings("unused")
private static void sendMessage(Session session, MessageProducer producer) throws JMSException{
for (int i = 0; i < SEND_NUM; i++) {
String message = "發送消息第" + (i + 1) + "條";
TextMessage text = session.createTextMessage(message);
System.out.println(message);
producer.send(text);
}
}
public static void run() throws Exception {
Connection connection = null;
Session session = null;
try {
// 創建鏈接工廠
ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
// 通過工廠創建一個連接
connection = factory.createConnection();
// 啓動連接
connection.start();
// 創建一個session會話
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 創建一個消息隊列
Destination destination = session.createQueue(DESTINATION);
// 創建消息製作者
MessageProducer producer = session.createProducer(destination);
// 設置持久化模式
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
sendMessage(session, producer);
// 提交會話
session.commit();
} catch (Exception e) {
throw e;
} finally {
// 關閉釋放資源
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
public static void main(String[] args) {
try {
MessageSender.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Queue方式
接受者
public class QueueReceiver {
// tcp 地址
public static final String BROKER_URL = "tcp://localhost:61616";
// 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
public static final String TARGET = "test.queue";
public static void run() throws Exception {
QueueConnection connection = null;
QueueSession session = null;
try {
// 創建鏈接工廠
QueueConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
// 通過工廠創建一個連接
connection = factory.createQueueConnection();
// 啓動連接
connection.start();
// 創建一個session會話
session = connection.createQueueSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 創建一個消息隊列
Queue queue = session.createQueue(TARGET);
// 創建消息製作者
javax.jms.QueueReceiver receiver = session.createReceiver(queue);
receiver.setMessageListener(new MessageListener() {
public void onMessage(Message msg) {
if (msg != null) {
MapMessage map = (MapMessage) msg;
try {
System.out.println(map.getLong("time") + "接收#" + map.getString("text"));
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
// 休眠100ms再關閉
Thread.sleep(1000 * 100);
// 提交會話
session.commit();
} catch (Exception e) {
throw e;
} finally {
// 關閉釋放資源
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
public static void main(String[] args) throws Exception {
QueueReceiver.run();
}
}
發送者
public class QueueSender {
// 發送次數
public static final int SEND_NUM = 5;
// tcp 地址
public static final String BROKER_URL = "tcp://localhost:61616";
// 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
public static final String DESTINATION = "test.queue";
public static void sendMessage(QueueSession session, javax.jms.QueueSender sender) throws Exception {
for (int i = 0; i < SEND_NUM; i++) {
String message = "發送消息第" + (i + 1) + "條";
MapMessage map = session.createMapMessage();
map.setString("text", message);
map.setLong("time", System.currentTimeMillis());
System.out.println(map);
sender.send(map);
}
}
public static void run() throws Exception {
QueueConnection connection = null;
QueueSession session = null;
try {
// 創建鏈接工廠
QueueConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
// 通過工廠創建一個連接
connection = factory.createQueueConnection();
// 啓動連接
connection.start();
// 創建一個session會話
session = connection.createQueueSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 創建一個消息隊列
Queue queue = session.createQueue(DESTINATION);
// 創建消息發送者
javax.jms.QueueSender sender = session.createSender(queue);
// 設置持久化模式
sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
sendMessage(session, sender);
// 提交會話
session.commit();
} catch (Exception e) {
throw e;
} finally {
// 關閉釋放資源
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
public static void main(String[] args) throws Exception {
QueueSender.run();
}
}
topic方式
接受者
public class TopicReceiver {
// tcp 地址
public static final String BROKER_URL = "tcp://localhost:61616";
// 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
public static final String TARGET = "hoo.mq.topic";
public static void run() throws Exception {
TopicConnection connection = null;
TopicSession session = null;
try {
// 創建鏈接工廠
TopicConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
// 通過工廠創建一個連接
connection = factory.createTopicConnection();
// 啓動連接
connection.start();
// 創建一個session會話
session = connection.createTopicSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 創建一個消息隊列
Topic topic = session.createTopic(TARGET);
// 創建消息製作者
TopicSubscriber subscriber = session.createSubscriber(topic);
subscriber.setMessageListener(new MessageListener() {
public void onMessage(Message msg) {
if (msg != null) {
MapMessage map = (MapMessage) msg;
try {
System.out.println(map.getLong("time") + "接收#" + map.getString("text"));
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
// 休眠100ms再關閉
Thread.sleep(1000 * 100);
// 提交會話
session.commit();
} catch (Exception e) {
throw e;
} finally {
// 關閉釋放資源
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
public static void main(String[] args) throws Exception {
TopicReceiver.run();
}
}
發送者
public class TopicSender {
// 發送次數
public static final int SEND_NUM = 5;
// tcp 地址
public static final String BROKER_URL = "tcp://localhost:61616";
// 目標,在ActiveMQ管理員控制檯創建 http://localhost:8161/admin/queues.jsp
public static final String DESTINATION = "hoo.mq.topic";
public static void sendMessage(TopicSession session, TopicPublisher publisher) throws Exception {
for (int i = 0; i < SEND_NUM; i++) {
String message = "發送消息第" + (i + 1) + "條";
MapMessage map = session.createMapMessage();
map.setString("text", message);
map.setLong("time", System.currentTimeMillis());
System.out.println(map);
publisher.send(map);
}
}
public static void run() throws Exception {
TopicConnection connection = null;
TopicSession session = null;
try {
// 創建鏈接工廠
TopicConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
// 通過工廠創建一個連接
connection = factory.createTopicConnection();
// 啓動連接
connection.start();
// 創建一個session會話
session = connection.createTopicSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 創建一個消息隊列
Topic topic = session.createTopic(DESTINATION);
// 創建消息發送者
TopicPublisher publisher = session.createPublisher(topic);
// 設置持久化模式
publisher.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
sendMessage(session, publisher);
// 提交會話
session.commit();
} catch (Exception e) {
throw e;
} finally {
// 關閉釋放資源
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
public static void main(String[] args) throws Exception {
TopicSender.run();
}
}
四、整合activeMQ
集成spring:引入jar包
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.14.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-spring</artifactId>
<version>5.14.1</version>
</dependency>
配置文件spring-context-activemq.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" xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-4.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.14.1.xsd">
<description>spring-activeMQ</description>
<!-- 獲取ActiveMQ提供的ConnectionFactory -->
<amq:connectionFactory id="amqConnectionFactory" brokerURL="tcp://127.0.0.1:61616" userName="admin" password="admin"></amq:connectionFactory>
<!-- spring連接activeMQ的conneciotnFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="amqConnectionFactory"></constructor-arg>
<property name="sessionCacheSize" value="100" />
</bean>
<!-- 定義JmsTemplate的Queue類型 -->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->
<constructor-arg ref="connectionFactory"></constructor-arg>
<!-- 非pub/sub模型(發佈/訂閱),即隊列模式 -->
<property name="pubSubDomain" value="false" />
</bean>
<!-- 定義JmsTemplate的Topic類型 -->
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->
<constructor-arg ref="connectionFactory"></constructor-arg>
<!-- pub/sub模型(發佈/訂閱) -->
<property name="pubSubDomain" value="true" />
</bean>
<bean id="queueReceiver" class="com.drink.modules.activemq.QueueReceiver"></bean>
<!-- 定義Queue監聽器 -->
<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
<jms:listener destination="test.queue" ref="queueReceiver"/>
</jms:listener-container>
<bean id="topicReceiver" class="com.drink.modules.activemq.TopicReceiver"></bean>
<!-- 定義Topic監聽器 -->
<jms:listener-container destination-type="topic" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
<jms:listener destination="test.topic" ref="topicReceiver"/>
</jms:listener-container>
</beans>
Queue接收文件:
public class QueueReceiver implements MessageListener {
@Override
public void onMessage(Message message) {
try {
System.out.println("QueueReceiver接收到消息:"+((TextMessage)message).getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
Topic接收文件:
public class TopicReceiver implements MessageListener {
@Override
public void onMessage(Message message) {
try {
System.out.println("TopicReceiver接收到消息:"+((TextMessage)message).getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
Queue發送文件:
@Component("queueSender")
public class QueueSender {
@Autowired
@Qualifier("jmsQueueTemplate")
private JmsTemplate jmsTemplate;
public void send(String queueName, final String message){
jmsTemplate.send(queueName,new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(message);
}
});
}
}
Topic發送文件:
@Component("topicSender")
public class TopicSender {
@Autowired
@Qualifier("jmsTopicTemplate")
private JmsTemplate jmsTemplate;
public void send(String queueName, final String message){
jmsTemplate.send(queueName,new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(message);
}
});
}
}
持久化到數據配置
在mysql中手動創建一個名稱爲activemq的數據庫,注意編碼格式。
將mysql驅動的jar包拷貝到apache-activemq-5.14.1\lib目錄下
修改conf下的activemq.xml文件
將默認的
<jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="true" />
修改爲
<!--createTablesOnStartup首次啓動創建表時設置爲true,其餘情況改爲false-->
<jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="true"/>
在broker節點後添加數據源
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/activemq"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
注意:這裏的版本是5.14.1,dbcp的包是commons-dbcp2-2.1.1.jar,所以這裏的classorg.apache.commons.dbcp2.BasicDataSource;
低版本的MQ配置爲org.apache.commons.dbcp.BasicDataSource
首次啓動後就會看到數據庫的創建的三張表
編碼中發送者需要設置持久化的方式
// 創建消息發送者
javax.jms.QueueSender sender = session.createSender(queue);
// 設置持久化模式
sender.setDeliveryMode(DeliveryMode.PERSISTENT);
spring中在JmsTemplate模板配置中設置
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->
<constructor-arg ref="connectionFactory"></constructor-arg>
<!-- 非pub/sub模型(發佈/訂閱),即隊列模式 -->
<property name="pubSubDomain" value="false" />
<!--1爲非持久化,2爲持久化-->
<property name="deliveryMode" value="2" />
</bean>