ActiveMQ入门(三)ActiveMQ的PS模型

本文详细介绍了ActiveMQ的发布订阅(PS)模式,包括概念解析、Java实现代码示例及运行流程。PS模式下,生产者将消息发布到Topic,所有订阅者都能消费到消息,适合一对多的消息传递场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

     本章讲解ActiveMQ的发布订阅模式,也就是PS(publish/subscribe)模型

方法

1.概念

我们之前说过ActiveMQ的PTP模式,也就是点对点模式。

而PS模式,是生产者将消息发布到Topic中,同时有多个消费者订阅(消费)该消息。和PTP模式不同的是,发布到Topic的消息会被所有的消费者消费。当生产者发布消息,不管是否有消费者,都不会保存消息。

2.使用Java实现PS模式

1)编写生产者代码

package cn.edu.ccut.test;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.junit.Test;

/**
 * 测试主动消费
 * 生产者代码
 * @author jwang
 *
 */
public class topic_producer {

	/**
	 * 发送消息到ActiveMQ中,具体的消息内容为参数信息
	 * 开发JMS相关代码过程中,使用的接口都是javax.jms包下的类型
	 * @param datas - 消息内容
	 */
	public void sendMessage(String datas){
		//连接工厂
		ConnectionFactory factory = null;
		//连接
		Connection connection = null;
		//目的地
		Destination destination = null;
		//会话
		Session session = null;
		//消息发送者
		MessageProducer producer = null;
		//消息对象
		Message message = null;
		try {
			//常见连接工厂,连接ActiveMQ服务的连接工厂
			//创建工厂,构造方法有三个参数,分别是用户名,密码,连接地址
			//无参构造,有默认的链接地址。本地连接。localhost
			//单参数构造,无验证模式的。没有用户的认证
			//三参数构造,有认证+指定地址
			factory = new ActiveMQConnectionFactory("admin", "admin", 
					"tcp://192.168.1.103:61616");
			//创建工厂,创建连接对象
			//创建连接的方法有重载,其中有createConnection(String username,String password);
			connection = factory.createConnection();
			//建议启动连接,消息的发送者不是必须启动连接,消息的消费者必须启动连接
			//producer在发送消息的时候,会检查是否启动了连接。如果未启动,自动启动
			//如果有特殊的配置,建议配置完毕后再启动连接
			connection.start();
			//通过连接对象,创建会话对象。
			/**
			 * 创建会话的时候,必须传递两个参数,分别代表是否支持事务和如何确认消息处理。
			 * transacted - 是否支持事务,数据类型是boolean。true - 支持,false - 不支持
			 * true - 支持事务,第二个参数对producer来说默认无效。建议传递的数据是Session.SESSION_TRANSACTED
			 * false - 不支持事务,常用参数。第二个参数必须传递,且必须有效。
			 * 
			 * acknoowledgeMode - 如何确认消息的处理,使用确认机制实现的。
			 * AUTO_ACKNOWLEDGE - 自动确认消息。消息的消费者处理消息后,自动确认。常用。
			 * CLIENT_ACKNOWLEDGE - 客户端手动确认。消息的处理者消费后,必须手工确认。
			 * DUPS_OK_ACKNOWLEDGE - 有副本的客户端手动确认
			 *     一个消息可以多次处理
			 *     可以降低Session的消耗,在可以容忍重复消息时使用。(不推荐使用)
			 */
			session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			//创建目的地。参数是目的地名称,是目的地的唯一标记
			destination = session.createTopic("test-topic");
			
			//创建会话对象,创建消息的发送者producer
			//创建的消息发送者,发送消息一定到指定的目的地中。
			producer = session.createProducer(destination);
			
			//创建文本消息对象,作为具体数据内容的载体.
			message = session.createTextMessage(datas);
			
			//使用producer,发送消息到ActiveMQ中的目的地。如果消息发送失败。抛出异常。
			producer.send(message);
			
			System.out.println("消息已发送");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//回收资源
			if(producer != null){ //回收消息发送者
				try {
					producer.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if(session != null){ //回收会话对象
				try {
					session.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if(connection != null){ //回收连接对象
				try {
					connection.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			
		}
	}
	@Test
	public void testProducer(){
		topic_producer producer = new topic_producer();
		producer.sendMessage("Topic-ActiveMQ!");
	}
	
}

2)编写消费者代码

package cn.edu.ccut.test;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
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;
import org.junit.Test;

/**
 * 测试主动消费
 * 消费者代码
 * @author jwang
 *
 */
public class topic_consumer {

	public String receiveTextMessage(){
		String result = "";
		ConnectionFactory factory = null;
		Connection connection = null;
		Destination destination = null;
		Session session = null;
		//消息的消费者,用于接收消息的对象。
		MessageConsumer consumer = null;
		Message message = null;
		try {
			factory = new ActiveMQConnectionFactory("admin", "admin", 
					"tcp://192.168.1.103:61616");
			connection = factory.createConnection();
			//消费者必须启动连接,否则无法处理消息
			connection.start();
			session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			destination = session.createTopic("test-topic");
			//创建消息的消费者。在指定的目的地中获取消息
			consumer = session.createConsumer(destination);
			//获取消息队列中的消息.receive方法是一个主动获取消息的方法,执行一次拉取一个消息。开发少用。
			message = consumer.receive();
			
			//处理文本消息
			result = ((TextMessage)message).getText();
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//回收资源
			if(consumer != null){ //回收消息消费者
				try {
					consumer.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if(session != null){ //回收会话对象
				try {
					session.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if(connection != null){ //回收连接对象
				try {
					connection.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			
		}
		return result;
	}
	@Test
	public void testConsumer(){
		topic_consumer consumer = new topic_consumer();
		String message = consumer.receiveTextMessage();
		
		System.out.println("消息内容是:"+message);
	}
	
}

我们先运行一下管理界面查看队列状态:

这里此刻只有我们测试PTP模式时的两个队列。

我们首先运行一下消费者代码订阅:

 

我们发现,此时它正在等待消息生产者发送消息。

我们这个时候看一下队列的状态,可以发现有topic存在,名字为test-topic

我们尝试运行生产者代码发送消息:

 

可以发现,发送的内容被订阅了。也就是成功的就收到了消息。

这个时候我们在观察队列:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值