activemq概念参考:
- https://www.cnblogs.com/linjiqin/p/6502940.html
- https://www.cnblogs.com/shyroke/p/7987039.html
试验环境:
- window7 x64
- jdk1.8
- maven-3.6
- eclipse 2018-12
- activemq-5.15.9
试验目的:
- 试验activemq的队列模型
- 试验activemq的发布订阅模型
试验工程代码下载: https://download.csdn.net/download/u010476739/11614637
一、ActiveMQ下载运行
下载页面:https://activemq.apache.org/components/classic/download/
将下载的压缩包解压到d盘,目录如下:
直接双击运行文件:D:\apache-activemq-5.15.9\bin\win64\activemq.bat
看到控制台输出如下:
此时在浏览器中输入:http://localhost:8161/admin/
用户名和密码都是:admin,然后可以看到如下图:
点击Queues,查看当前队列信息:
点击Topics,查看发布订阅(主题)信息:
二、试验activemq的队列消息模型
2.1 eclipse中新建maven工程“activemq-demo”
它的pom文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jackletter</groupId>
<artifactId>activemq-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-all -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.9</version>
</dependency>
</dependencies>
</project>
2.2 新建类“com.jackletter.JMSProducer”:消息生产者
package com.jackletter;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 消息的生产者(发送者)
*
* @author Administrator
*
*/
public class JMSProducer {
public static void main(String[] args) {
try {
// 第一步:建立ConnectionFactory工厂对象,需要填入用户名、密码、以及要连接的地址,均使用默认即可,默认端口为"tcp://localhost:61616"
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER,
ActiveMQConnectionFactory.DEFAULT_PASSWORD, "failover:(tcp://localhost:61616)?Randomize=false");
// 第二步:通过ConnectionFactory工厂对象我们创建一个Connection连接,并且调用Connection的start方法开启连接,Connection默认是关闭的。
Connection connection = connectionFactory.createConnection();
connection.start();
// 第三步:通过Connection对象创建Session会话(上下文环境对象),用于接收消息,参数配置1为是否启用是事务,参数配置2为签收模式,一般我们设置自动签收。
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 第四步:通过Session创建Destination对象,指的是一个客户端用来指定生产消息目标和消费消息来源的对象,在PTP模式中,Destination被称作Queue即队列;在Pub/Sub模式,Destination被称作Topic即主题。在程序中可以使用多个Queue和Topic。
Destination destination = session.createQueue("HelloWorld");
// 第五步:我们需要通过Session对象创建消息的发送和接收对象(生产者和消费者)MessageProducer/MessageConsumer。
MessageProducer producer = session.createProducer(null);
// 第六步:我们可以使用MessageProducer的setDeliveryMode方法为其设置持久化特性和非持久化特性(DeliveryMode),我们稍后详细介绍。
// producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 第七步:最后我们使用JMS规范的TextMessage形式创建数据(通过Session对象),并用MessageProducer的send方法发送数据。同理客户端使用receive方法进行接收数据。最后不要忘记关闭Connection连接。
for (int i = 0; i < 10; i++) {
TextMessage msg = session.createTextMessage("我是消息内容" + i);
// 第一个参数目标地址
// 第二个参数 具体的数据信息
// 第三个参数 传送数据的模式
// 第四个参数 优先级
// 第五个参数 消息的过期时间 过期时间是毫秒,这里设置的是100毫秒(时间短的话控制台看不到效果)
producer.send(destination, msg, DeliveryMode.NON_PERSISTENT, 0, 1000L * 100);
System.out.println("发送消息:" + msg.getText());
session.commit(); // 启用事务时记得提交事务,不然消费端接收不到消息
Thread.sleep(1000);
}
if (connection != null) {
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.3 新建类“com.jackletter.JMSConsumer”:消息消费者
package com.jackletter;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 消息的消费者(接受者)
*
* @author Administrator
*
*/
public class JMSConsumer {
public static void main(String[] args) {
try {
// 第一步:建立ConnectionFactory工厂对象,需要填入用户名、密码、以及要连接的地址,均使用默认即可,默认端口为"tcp://localhost:61616"
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER,
ActiveMQConnectionFactory.DEFAULT_PASSWORD, "failover:(tcp://localhost:61616)?Randomize=false");
// 第二步:通过ConnectionFactory工厂对象我们创建一个Connection连接,并且调用Connection的start方法开启连接,Connection默认是关闭的。
Connection connection = connectionFactory.createConnection();
connection.start();
// 第三步:通过Connection对象创建Session会话(上下文环境对象),用于接收消息,参数配置1为是否启用是事务,参数配置2为签收模式,一般我们设置自动签收。
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 第四步:通过Session创建Destination对象,指的是一个客户端用来指定生产消息目标和消费消息来源的对象,在PTP模式中,Destination被称作Queue即队列;在Pub/Sub模式,Destination被称作Topic即主题。在程序中可以使用多个Queue和Topic。
Destination destination = session.createQueue("HelloWorld");
// 第五步:通过Session创建MessageConsumer
MessageConsumer consumer = session.createConsumer(destination);
while (true) {
TextMessage msg = (TextMessage) consumer.receive();
if (msg == null) {
break;
}
System.out.println("收到的内容:" + msg.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.4 整个工程目录结构:
2.5 首先运行消息生产者:
2.6 查看activemq的控制台
可以看到activemq的队列中已经有10个未消费的消息
2.7 再运行消息消费者
可以看到:消费者消费了上面发的10个消息
此时再看一下activemq的控制台:
可以看到控制台上也显示队列的消息已经被全部消费了
三、试验activemq的发布订阅模型
为了试验这个模型,这里新建了两个maven工程,分别运行eclipse加载工程
3.1 新建订阅者工程“activemq-demo-sub”,并运行
工程pom文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jackletter</groupId>
<artifactId>activemq-demo-sub</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-all -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.9</version>
</dependency>
</dependencies>
</project>
新建类“com.jackletter.sub.JMSConsumer”:
package com.jackletter.sub;
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.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class JMSConsumer {
private static final String USERNAME = ActiveMQConnection.DEFAULT_USER; // 默认的连接用户名
private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD; // 默认的连接密码
private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL; // 默认的连接地址
private static int counter = 0;
public static void main(String[] args) {
for (int i = 0; i < 4; i++) {
new Runnable() {
@Override
public void run() {
try {
ConnectionFactory connectionFactory; // 连接工厂
Connection connection = null; // 连接
Session session; // 会话 接受或者发送消息的线程
Destination destination; // 消息的目的地
MessageConsumer consumer; // 创建消费者
// 实例化连接工厂
connectionFactory = new ActiveMQConnectionFactory(JMSConsumer.USERNAME, JMSConsumer.PASSWORD,
JMSConsumer.BROKEURL);
connection = connectionFactory.createConnection(); // 通过连接工厂获取连接
connection.start(); // 启动连接
/**
* 这里的最好使用Boolean.FALSE,如果是用true则必须commit才能生效,且http://127.0.0.1:8161/admin管理页面才会更新消息队列的变化情况。
*/
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); // 创建Session
// destination=session.createQueue("FirstQueue1"); // 创建消息队列
destination = session.createTopic("firstTopic");
consumer = session.createConsumer(destination);
int counter = JMSConsumer.counter++;
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
try {
System.out.println("订阅者" + counter + "收到的消息:" + ((TextMessage) message).getText());
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}); // 注册消息监听
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.run();
}
}
}
整个工程目录结构:
运行这个工程:
3.2 查看activemq控制台
可以看到,控制台显示主题“firstTopic”有四个订阅者。
3.3 新建发布者工程“activemq-demo-pub”,并运行
工程pom文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jackletter</groupId>
<artifactId>activemq-demo-pub</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-all -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.9</version>
</dependency>
</dependencies>
</project>
新建发布者类“com.jackletter.pub.JMSProducer”:
package com.jackletter.pub;
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.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 消息生产者
*
* @author Administrator
*
*/
public class JMSProducer {
private static final String USERNAME = ActiveMQConnection.DEFAULT_USER; // 默认的连接用户名
private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD; // 默认的连接密码
private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL; // 默认的连接地址
private static final int SENDNUM = 10; // 发送的消息数量
public static void main(String[] args) {
ConnectionFactory connectionFactory; // 连接工厂
Connection connection = null; // 连接
Session session; // 会话 接受或者发送消息的线程
Destination destination; // 消息的目的地
MessageProducer messageProducer; // 消息生产者
// 实例化连接工厂
connectionFactory = new ActiveMQConnectionFactory(JMSProducer.USERNAME, JMSProducer.PASSWORD,
JMSProducer.BROKEURL);
try {
connection = connectionFactory.createConnection(); // 通过连接工厂获取连接
connection.start(); // 启动连接
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE); // 创建Session
// destination=session.createQueue("FirstQueue1"); // 创建消息队列
destination = session.createTopic("firstTopic");
messageProducer = session.createProducer(destination); // 创建消息生产者
for (int i = 0; i < JMSProducer.SENDNUM; i++) {
TextMessage message = session.createTextMessage("ActiveMQ 发布的消息" + i);
System.out.println("发送消息:" + "ActiveMQ 发布的消息" + i);
messageProducer.send(message);
Thread.sleep(2000);
}
session.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
整个工程目录结构:
运行这个工程:
可以看到发布者发布了10个消息
那么此时查看下activemq的控制台:
可以看到,现在共有4个消费者,消息入栈10次,出栈40次
再看一下消费者控制台输出:
可以看到4个消费者共消费数据40次。