ActiveMQ的使用分为两种,一种是嵌入式,即把ActiveMQ作为内嵌的JMS provider集成到Tomcat或其他Web服务器中;另一种是独立部署,即ActiveMQ单独部署,独立运行,通过ActiveMQ提供的API进行进程外访问。为了更有利于业务的解耦和工程部署结构的分离;也有利于对ActiveMQ进行配置定制和优化,可以采用独立部署的方式使用ActiveMQ。
JMS 支持两种截然不同的消息传送模型:PTP(即点对点模型)和Pub/Sub(即发布/订阅模型),分别称作:PTP Domain 和Pub/Sub Domain。
PTP(使用Queue即队列目标) 消息从一个生产者传送至一个消费者。在此传送模型中,目标是一个队列。消息首先被传送至队列目标,然后根据队列传送策略,从该队列将消息传送至向此队列进行注册的某一个消费者,一次只传送一条消息。可以向队列目标发送消息的生产者的数量没有限制,但每条消息只能发送至、并由一个消费者成功使用。如果没有已经向队列目标注册的消费者,队列将保留它收到的消息,并在某个消费者向该队列进行注册时将消息传送给该消费者。
Pub/Sub(使用Topic即主题目标) 消息从一个生产者传送至任意数量的消费者。在此传送模型中,目标是一个主题。消息首先被传送至主题目标,然后传送至所有已订阅此主题的活动消费者。可以向主题目标发送消息的生产者的数量没有限制,并且每个消息可以发送至任意数量的订阅消费者。主题目标也支持持久订阅的概念。持久订阅表示消费者已向主题目标进行注册,但在消息传送时此消费者可以处于非活动状态。当此消费者再次处于活动状态时,它将接收此信息。如果没有已经向主题目标注册的消费者,主题不保留其接收到的消息,除非有非活动消费者注册了持久订阅。
下面我们通过代码演示ActiveMQ对以上2种消息模式的使用方式。
引入activeMQ jar包
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.8.0</version>
</dependency>
一、队列模型
在点对点的传输方式中,消息数据被持久化,每条消息都能被消费,没有监听QUEUE地址也能被消费,数据不会丢失,一对一的发布接受策略,保证数据完整。
生产者:
package cn.slimsmart.activemq.demo.queue;
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.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
//队列
public class Producer {
public static void main(String[] args) throws Exception {
// 连接工厂,JMS 用它创建连接
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://192.168.18.43:61616");
// 构造从工厂得到连接对象
Connection connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接 一个发送或接收消息的线程
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值slimsmart.queue是一个queue
Destination destination = session.createQueue("slimsmart.queue.test");
// 得到消息生成者【发送者】
MessageProducer producer = session.createProducer(destination);
// 设置持久化,
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
// 构造消息,并发送
sendMessage(session, producer);
//提交
session.commit();
session.close();
connection.close();
}
public static void sendMessage(Session session, MessageProducer producer) throws Exception {
for (int i = 1; i <= 5; i++) {
TextMessage message = session.createTextMessage("发送的消息" + i);
// 发送消息到目的地方
System.out.println("发送消息:" + "发送的消息" + i);
producer.send(message);
}
}
}
消费者:
package cn.slimsmart.activemq.demo.queue;
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 Consumer {
public static void main(String[] args) throws Exception {
// 连接工厂,JMS 用它创建连接
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://192.168.18.43:61616");
// 构造从工厂得到连接对象
Connection connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接 一个发送或接收消息的线程
//第一个参数为true 标识开启事务,需要手工commit
final Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值slimsmart.queue是一个服务器的queue,星号*匹配任意字符
Destination destination = session.createQueue("slimsmart.queue.test");
// 消费者,消息接收者
MessageConsumer consumer = session.createConsumer(destination);
consumer.setMessageListener( new MessageListener() {
public void onMessage(Message message) {
TextMessage textMsg = (TextMessage)message;
try {
System.out.println("收到消息" + textMsg.getText());
//session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
Thread.sleep(100000);
/*
while (true) {
//设置接收者接收消息的时间,为了便于测试,这里设定为100s
TextMessage message = (TextMessage) consumer.receive(100000);
if (null != message) {
System.out.println("收到消息" + message.getText());
} else {
break;
}
}*/
session.close();
connection.close();
}
}
二、主题模型
在发布订阅消息方式中,消息是无状态的,不保证每条消息被消费,只有监听该TOPIC地址才能收到消息并消费,否则该消息将会丢失。一对多的发布接受策略,可以同时消费多个消息。
生产者:
package cn.slimsmart.activemq.demo.topic;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Producer {
public static void main(String[] args) throws JMSException {
// 连接到ActiveMQ服务器
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.18.43:61616");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Topic topic = session.createTopic("slimsmart.topic.test");
MessageProducer producer = session.createProducer(topic);
// NON_PERSISTENT 非持久化 PERSISTENT 持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
TextMessage message = session.createTextMessage();
message.setText("topic 消息。");
message.setStringProperty("property", "消息Property");
// 发布主题消息
producer.send(message);
System.out.println("Sent message: " + message.getText());
session.commit();
session.close();
connection.close();
}
}
消费者:
package cn.slimsmart.activemq.demo.topic;
import javax.jms.Connection;
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 javax.jms.Topic;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Consumer {
public static void main(String[] args) throws JMSException {
// 连接到ActiveMQ服务器
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.18.43:61616");
Connection connection = factory.createConnection();
connection.start();
final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Topic topic = session.createTopic("slimsmart.topic.test");
// 创建订阅
MessageConsumer consumer = session.createConsumer(topic);
consumer.setMessageListener(new MessageListener() {
// 订阅接收方法
public void onMessage(Message message) {
TextMessage tm = (TextMessage) message;
try {
System.out.println("Received message: " + tm.getText()+":"+tm.getStringProperty("property"));
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
}
}