ActiveMQ中一般有两种消息队列,一是点对点模式(p2p),二是发布/订阅模式(pub/sub)。
在进行demo测试之前,我们先建立一个maven工程,引入相应的包:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.10</version>
</dependency>
或者
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.15.10</version>
</dependency>
点对点模式:
点对点的模式主要建立在一个队列上面,当连接一个列队的时候,发送端不需要知道接收端是否正在接收,可以直接向ActiveMQ发送消息,发送的消息,将会先进入队列中,如果有接收端在监听,则会发向接收端,如果没有接收端接收,则会保存在ActiveMQ服务器,直到接收端接收消息,点对点的消息模式可以有多个发送端,多个接收端,但是一条消息,只会被一个接收端给接收到,哪个接收端先连上ActiveMQ,则会先接收到,而后来的接收端则接收不到那条消息。
我们先建立一个生产者:
public class QueueProducer {
public static void main(String[] args) throws Exception {
// 1.创建连接工厂,服务器ip记得修改为自己的,端口号是61616,不是ActiveMQ服务器的端口号8161
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.232.135:61616");
// 2.获取连接
Connection connection = connectionFactory.createConnection();
// 3.启动连接
connection.start();
// 4.获取session (参数1:是否启动事务,参数2:消息确认模式)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 5.创建队列对象
Queue queue = session.createQueue("test-queue");
// 6.创建消息生产者
MessageProducer producer = session.createProducer(queue);
// 7.创建消息
TextMessage textMessage = session.createTextMessage("点对点消息队列测试");
// 8.发送消息
producer.send(textMessage);
// 9.关闭资源
producer.close();
session.close();
connection.close();
System.out.println("消息生产成功.....");
}
}
接着建立消费者:
public class QueueConsumer {
public static void main(String[] args) throws JMSException, IOException {
//1.创建连接工厂
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("tcp://192.168.232.135:61616");
//2.获取连接
Connection connection = connectionFactory.createConnection();
//3.启动连接
connection.start();
//4.获取session (参数1:是否启动事务,参数2:消息确认模式)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.创建队列对象
Queue queue = session.createQueue("test-queue");
//6.创建消息消费
MessageConsumer consumer = session.createConsumer(queue);
//7.监听消息
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
TextMessage textMessage=(TextMessage)message;
try {
System.out.println("接收到消息:"+textMessage.getText());
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
我们这里是将消费者使用异步监听的方式进行监听的,也就是使用的是MessageConsumer中的setMessageListener(MessageListener listener) ,还有一种方式是使用同步的方法,也就是MessageConsumer中的recive(),只需要把第7步监听消息修改为consumer.recive()即可。
我们先启动生产者,这时候我们查看ActiveMQ服务器中的Queues可以发现生产了一条消息:
接着启动消费者,可以看到会直接把此消息给消费掉:
如果我们同时启动两个消费者,然后让生产者多生产几条消息,我们通过控制台可以发现,每条消息只会被一个消费者接收过来消费,关于消费者之间如何确定谁去消费,后期我会详细解释,这里只做简单的介绍。
发布/订阅模式:
在发布/订阅消息模型中,发布者发布一个消息,该消息通过Topic传递给所有的客户端。该模式下,发布者与订阅者都是匿名的,即发布者与订阅者都不知道对方是谁。并且可以动态的发布与订阅Topic。Topic主要用于保存和传递消息,且会一直保存消息直到消息被传递给客户端。一个消息可以被多个消费者给消费掉,但只有当你订阅后才会去消费,订阅之前的消息都不会被消费。
首先建立生成者:
public class TopicProducer {
public static void main(String[] args) throws JMSException {
//1.创建连接工厂
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("tcp://192.168.232.135:61616");
//2.获取连接
Connection connection = connectionFactory.createConnection();
//3.启动连接
connection.start();
//4.获取session (参数1:是否启动事务,参数2:消息确认模式)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.创建主题对象
Topic topic = session.createTopic("test-topic");
//6.创建消息生产者
MessageProducer producer = session.createProducer(topic);
//7.创建消息
TextMessage textMessage = session.createTextMessage("发布/订阅模式消息队列");
//8.发送消息
producer.send(textMessage);
//9.关闭资源
producer.close();
session.close();
connection.close();
}
}
接着我们来建立消费者:
public class TopicConsumer {
public static void main(String[] args) throws JMSException {
//1.创建连接工厂
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("tcp://192.168.232.135:61616");
//2.获取连接
Connection connection = connectionFactory.createConnection();
//3.启动连接
connection.start();
//4.获取session (参数1:是否启动事务,参数2:消息确认模式)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//5.创建主题对象
//Queue queue = session.createQueue("test-queue");
Topic topic = session.createTopic("test-topic");
//6.创建消息消费
MessageConsumer consumer = session.createConsumer(topic);
//7.监听消息
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
TextMessage textMessage=(TextMessage)message;
try {
System.out.println("接收到消息:"+textMessage.getText());
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
开启生产者,然后打开ActiveMQ的Topics界面,我们可以看到创建了一条消息:
接着打开消费者,此时我们会发现,消息并没有被消费掉,因为我们是先用生产者发布消息,再让消费者进行订阅的,所以此时并没有被消费掉。
如果我们再启动生产者生产一条消息,此时是会被消费者消费掉的:
如果我们再启动一个消费者,然后让生产者再发布一条消息,我们会发现这条消息被这两个消费者都消费掉,也就是这两个消费者都会去消费这条消息:
整个工作流程如下:
①创建工厂ConnectionFactary
②通过工厂获取连接Connection
③启动连接
④通过连接获取会话Session
⑤通过会话创建队列Queue(点对点)或者订阅Topic(订阅)
⑥通过会话创建创建消息生产者
⑦创建消息
⑧发送或接收(注册监听)消息
⑨关闭连接
在消费者中可以不要第⑨步,因为关闭了的话,在使用异步的方式的时候,即MessageConsumer中的setMessageListener(MessageListener listener)是没法进行消息消费的。就算是使用同步的方式,即MessageConsumer中的receive()时,也是只能启动一次消费一条消息。
通过这两种模式的操作,我们应该能发现这两者的不同之处,点对点是不管消息是否先生产,只要最后有消费者,就能被成功消费,而发布/订阅模式中,只有在消息被订阅后,才会被消费,在订阅之前的消息,都不会被消费掉。