官方文檔地址
https://activemq.apache.org/index.html
簡介
activemq是實現消息隊列的一個框架,主要有兩套功能:隊列,發佈/訂閱
隊列涉及到兩個概念:生產者與消費者。一個生產消息,一個消費消息。
發佈/訂閱涉及到三個概念:發佈者,訂閱者,主題。主題其實就是一個字符串,一個名字。發佈者在這個名下發消息,所有訂閱這個主題(監控這個字符串)的訂閱者收到消息。
具體來說這其中還有很多特性,最核心的大概就是完全的解耦了吧。其他還有不少額外的功能,比如異步發送,持久化,等待隊列等等。
安裝
windows本地測試
https://activemq.apache.org/components/classic/download/
下載解壓。
啓動方法一:apache-activemq-5.15.11\bin\win64\InstallService.bat 註冊服務,之後在服務頁面將activeMq服務開啓即可使用。
啓動方法二:在dos進入目錄apache-activemq-5.15.11\bin,執行activemq start來啓動(關閉窗口會導致服務關閉)
這種方法在windows下問題不少,需要計算機名中沒有-
,Internet Connection Sharing (ICS)服務必須關閉,不然會報端口占用的錯誤。address already in use: JVM_BIND
。
在瀏覽器中輸入http://127.0.0.1:8161進入管理頁面。
默認賬號/密碼是admin/admin
示例
添加依賴包
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.9.0</version>
</dependency>
隊列測試代碼
https://activemq.apache.org/hello-world
最簡單的一套測試代碼
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* Hello world!
*/
public class App {
public static void main(String[] args) throws Exception {
org.apache.activemq.broker.jmx.ManagementContext a;
thread(new HelloWorldProducer(), false);
thread(new HelloWorldProducer(), false);
thread(new HelloWorldConsumer(), false);
thread(new HelloWorldConsumer(), false);
thread(new HelloWorldConsumer(), false);
thread(new HelloWorldConsumer(), false);
// Thread.sleep(1000);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldProducer(), false);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldProducer(), false);
// Thread.sleep(1000);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldProducer(), false);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldProducer(), false);
// thread(new HelloWorldProducer(), false);
// Thread.sleep(1000);
// thread(new HelloWorldProducer(), false);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldProducer(), false);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldProducer(), false);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldProducer(), false);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldConsumer(), false);
// thread(new HelloWorldProducer(), false);
}
public static void thread(Runnable runnable, boolean daemon) {
Thread brokerThread = new Thread(runnable);
brokerThread.setDaemon(daemon);
brokerThread.start();
}
public static class HelloWorldProducer implements Runnable {
public void run() {
try {
// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic or Queue)
//創建主題或隊列
Destination destination = session.createQueue("TEST.FOO");
//session.createTopic("TOPIC.FOO");
// Create a MessageProducer from the Session to the Topic or Queue
MessageProducer producer = session.createProducer(destination);
//持久化
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// Create a messages
String text = "Hello world! From: " + Thread.currentThread().getName() + " : " + this.hashCode();
TextMessage message = session.createTextMessage(text);
// Tell the producer to send the message
//發送消息
//System.out.println("Sent message: "+ message.hashCode() + " : " + Thread.currentThread().getName());
System.out.println("Sent message: "+ this.hashCode() + " : " + Thread.currentThread().getName());
producer.send(message);
// Clean up
session.close();
connection.close();
}
catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
}
public static class HelloWorldConsumer implements Runnable, ExceptionListener {
public void run() {
try {
// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
connection.setExceptionListener(this);
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic or Queue)
Destination destination = session.createQueue("TEST.FOO");
// Create a MessageConsumer from the Session to the Topic or Queue
MessageConsumer consumer = session.createConsumer(destination);
// Wait for a message
Message message = consumer.receive(1000);
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
String text = textMessage.getText();
System.out.println("Received: " + text);
} else {
System.out.println("Received: " + message);
}
consumer.close();
session.close();
connection.close();
} catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
public synchronized void onException(JMSException ex) {
System.out.println("JMS Exception occured. Shutting down client.");
}
}
}
執行後控制檯輸出
Sent message: 365885423 : Thread-0
Sent message: 1671555210 : Thread-1
Received: Hello world! From: Thread-1 : 1671555210
Received: Hello world! From: Thread-0 : 365885423
Received: null
Received: null
代碼很簡單沒有什麼需要解釋的,但是有一個問題是,執行的結果無法在監控頁面http://127.0.0.1:8161/admin/queues.jsp
中顯示出來,推測應該是與這個vm的協議有關,將連接url換成tcp://127.0.0.1:61616
執行後可以在監控頁面顯示。具體要替換的url在
apache-activemq-5.15.11\conf\activemq.xml
中有配置
package yyst.myTest.activemq;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* Hello world!
*/
public class App {
//private static final String ACTIVEMQ_URL = "vm://localhost";
private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";
public static void main(String[] args) throws Exception {
thread(new HelloWorldProducer(), false);//發送
thread(new HelloWorldProducer(), false);
thread(new HelloWorldConsumer(), false);//接收
}
public static void thread(Runnable runnable, boolean daemon) {
Thread brokerThread = new Thread(runnable);
brokerThread.setDaemon(daemon);
brokerThread.start();
}
public static class HelloWorldProducer implements Runnable {
public void run() {
try {
// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic or Queue)
//創建主題或隊列
Destination destination = session.createQueue("TEST.FOO");
//session.createTopic("TOPIC.FOO");
// Create a MessageProducer from the Session to the Topic or Queue
MessageProducer producer = session.createProducer(destination);
//持久化
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// Create a messages
String text = "Hello world! From: " + Thread.currentThread().getName() + " : " + this.hashCode();
TextMessage message = session.createTextMessage(text);
// Tell the producer to send the message
//發送消息
//System.out.println("Sent message: "+ message.hashCode() + " : " + Thread.currentThread().getName());
System.out.println("Sent message: "+ this.hashCode() + " : " + Thread.currentThread().getName());
producer.send(message);
// Clean up
session.close();
connection.close();
}
catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
}
public static class HelloWorldConsumer implements Runnable, ExceptionListener {
public void run() {
try {
// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
connection.setExceptionListener(this);
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic or Queue)
Destination destination = session.createQueue("TEST.FOO");
// Create a MessageConsumer from the Session to the Topic or Queue
MessageConsumer consumer = session.createConsumer(destination);
// Wait for a message
Message message = consumer.receive(1000);
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
String text = textMessage.getText();
System.out.println("Received: " + text);
} else {
System.out.println("Received: " + message);
}
consumer.close();
session.close();
connection.close();
} catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
public synchronized void onException(JMSException ex) {
System.out.println("JMS Exception occured. Shutting down client.");
}
}
}
如果僅僅是測試的話,也可以再這裏進行
http://127.0.0.1:8161/admin/send.jsp
發佈/訂閱
與隊列的代碼差不多,基本就是createQueue改成createTopic,然後消費者的接收方法改爲監聽。
生產者
public static class HelloWorldTopicProducer implements Runnable {
public void run() {
try {
// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic or Queue)
//創建主題或隊列
Destination destination = session.createTopic("TOPIC.FOO");
//session.createTopic("TOPIC.FOO");
// Create a MessageProducer from the Session to the Topic or Queue
MessageProducer producer = session.createProducer(destination);
//持久化
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// Create a messages
String text = "Hello world! From: " + Thread.currentThread().getName() + " : " + this.hashCode();
TextMessage message = session.createTextMessage(text);
// Tell the producer to send the message
//發送消息
//System.out.println("Sent message: "+ message.hashCode() + " : " + Thread.currentThread().getName());
System.out.println("Sent message: "+ this.hashCode() + " : " + Thread.currentThread().getName());
producer.send(message);
// Clean up
session.close();
connection.close();
}
catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
}
消費者
public static class HelloWorldTopicConsumer implements Runnable, ExceptionListener {
public void run() {
try {
// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
connection.setExceptionListener(this);
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic or Queue)
Destination destination = session.createTopic("TOPIC.FOO");
// Create a MessageConsumer from the Session to the Topic or Queue
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();
}
}
});
// consumer.close();
// session.close();
// connection.close();
} catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
public synchronized void onException(JMSException ex) {
System.out.println("JMS Exception occured. Shutting down client.");
}
}
測試代碼
thread(new HelloWorldTopicConsumer(), false);
thread(new HelloWorldTopicProducer(), false);
Thread.sleep(1000);
thread(new HelloWorldTopicConsumer(), false);
thread(new HelloWorldTopicConsumer(), false);
Thread.sleep(1000);
thread(new HelloWorldTopicProducer(), false);
輸出
Sent message: 514035740 : Thread-1
消費的消息:Hello world! From: Thread-1 : 514035740
Sent message: 1898887496 : Thread-6
消費的消息:Hello world! From: Thread-6 : 1898887496
消費的消息:Hello world! From: Thread-6 : 1898887496
消費的消息:Hello world! From: Thread-6 : 1898887496