官方文档地址
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