ActiveMQ入门笔记

下载

官网http://activemq.apache.org
在这里插入图片描述在这里插入图片描述

安装

使用XShell上传到Linux服务器

XShell上传文件

解压即可使用
tar -zxvf 文件名
参数含义
z通过gzip指令处理备份文件
x从备份文件中还原文件
v显示指令执行过程
f指定备份文件

在这里插入图片描述

版本查看可以通过release notes

因为我安装的JDK版本为1.7,所以下载了5.9.0版本的activemq;如果使用5.10.x,需要安装JDk1.8+;

配置

重要配置文件
activemq.xml

配置的是 ActiveMQ 应用使用的默认对象组件

jetty.xml

配置 jetty 服务器的默认对象组件

users.properties

内容信息: 用户名=密码,是用于配置客户端通过协议访问 ActiveMQ 时,使用的用户名和密码.

启动

命令:路径/bin/activemq start

在这里插入图片描述
在这里插入图片描述

浏览器访问

activemq部署在jetty服务器上,启动activemq时,jetty相关服务也会被启动,我们可以通过浏览器访问!!!

开放8161端口

在这里插入图片描述

  • jetty默认端口是8161,所以需要开放8161端口。修改/etc/sysconfig/iptables文件
    在这里插入图片描述

  • 重启服务:service iptables restart

可通过浏览器访问

通过ip:8161/admin访问,用户名和密码都为admin,因为users.properties文件中最初就保存了这组用户名和密码。
在这里插入图片描述

启动成功

在这里插入图片描述

重启

命令:路径/bin/activemq restart

停止

命令:路径/bin/activemq stop

简介

核心概念
关键词概念
Destination消息发送和获取的目的地,JMS Provider(消息中间件)负责维护,用于对 Message 进行管理的对象。 MessageProducer 需要指定 Destination 才能发送消息,MessageConsumer 需要指定 Destination 才能接收消息。
Producer消 息 生成 者 (客 户 端、 生 成 消 息 ), 负 责 发送 Message 到 目 的地 。 应 用 接口 为 MessageProducer。在 JMS 规范中,所有的标准定义都在 javax.jms 包中。
Consumer消息消费者(处理消息),负责从目的地中消费【处理|监听|订阅】Message。应用接口 为 MessageConsumer
Message消息(Message),消息封装一次通信的内容。常见类型有:StreamMessage、BytesMessage、 TextMessage、ObjectMessage、MapMessage。
开发相关知识
关键词概念
ConnectionFactory链接工厂, 用于创建链接的工厂类型。 注意,不能和 JDBC 中的 ConnectionFactory 混 淆。
Connection链接. 用于建立访问 ActiveMQ 连接的类型, 由链接工厂创建. 注意,不能和 JDBC 中的 Connection 混淆。
Session会话, 一次持久有效有状态的访问. 由链接创建. 是具体操作消息的基础支撑。
QueueQueue 是队列形式的目的地,是 Destination 的子接口,Queue 特点: 队列中的消息,默认只能由唯一的一个消费者处理。一旦处理消息删除。
TopicTopic 是主题形式目的地,是 Destination 的子接口,Topic 特点:主题中的消息,会发送给所有的消费者同时处理。只有在消息可以重复处理的业务场景中可使用。
PTPPoint to Point。点对点消息模型。就是基于 Queue 实现的消息处理方式。
PUB & SUBPublish & Subscribe 。消息的发布/订阅模型。是基于 Topic 实现的消息处理方式。

应用

activemq默认端口为61616,所以发送消息和消费消息时,端口应该是61616,而不是jetty的8161。activemq是部署在jetty服务器上的类似于你将web项目部署在tomcat上。

开放61616端口

linux服务器需要开放61616端口,才能被外部主机访问到。

导包

导入activemq-all-XXX.jar

  • 如:
    在这里插入图片描述
PTP处理模式(Queue)- 主动消费
Producer
  • 代码
public class PTP_Producer {
	// 连接工厂
	private ConnectionFactory factory = null;
	// 连接
	private Connection conn = null;
	// 会话
	private Session session = null;
	// 目的地
	private Destination destination = null;
	// 消息生产者
	private MessageProducer producer = null;
	// 消息
	private TextMessage textMessage = null;
	
	private void sendMessage(String message) {
		factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.65.128:61616");
		
		try {
			conn = factory.createConnection();
			
			conn.start();
			// 不是批量发送,不建议开启事务
			// 开启客户端确认消息
			session = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
			
			destination = session.createQueue("first");
			
			producer = session.createProducer(destination);
			
			textMessage = session.createTextMessage(message);
			
			producer.send(textMessage);
			
			System.out.println("消息已发送!");
		} catch (JMSException e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		PTP_Producer p = new PTP_Producer();
		p.sendMessage("hello world!");
	}
}
  • 运行结果

在这里插入图片描述

可以看到,消息生产者成功创建了一个名为first的队列,并发送了一条消息!!!

Consumer
public class PTP_Consumer {
	// 连接工厂
	private ConnectionFactory factory = null;
	// 连接
	private Connection conn = null;
	// 会话
	private Session session = null;
	// 目的地
	private Destination destination = null;
	// 消息
	private TextMessage message = null;
	// 消息消费者
	private MessageConsumer consumer = null;
	// 返回结果
	private static String text = null;
	
	public String receive() {
		factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.65.128:61616");
		
		try {
			conn = factory.createConnection();
			
			conn.start();
			// 开启自动确认
			session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
			
			destination = session.createQueue("first");
			
			consumer = session.createConsumer(destination);
			
			message = (TextMessage) consumer.receive();
			
			text = message.getText();
			
		} catch (JMSException e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
		
		return text;
	}
	
	public static void main(String[] args) {
		PTP_Consumer c = new PTP_Consumer();
		String receive = c.receive();
		System.out.println(receive);
	}
}
  • 运行结果
    在这里插入图片描述

消费者从队列中取出消息并确认消费!!!并且,如果队列中没有消息时,消费者会阻塞等待,直到有生产者发送了消息,但可以设置等待时长!

PTP处理模式(Queue)- 观察者模式

对消费者使用监听的方式,实现消息的处理,可以一次性注册多个consumer。给consumer注册监听器后,只要线程不关闭,就会一直轮询处理Queue中的消息。

Producer
  • 代码
public class PTP_Producer_Listener {
	// 连接工厂
	private ConnectionFactory factory = null;
	// 连接
	private Connection connection = null;
	// 会话
	private Session session = null;
	// 目的地
	private Destination destination = null;
	// 消息生产者
	private MessageProducer producer = null;
	// 消息
	private TextMessage textMessage = null;
	
	public void sendMessage(String message) {
		factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.65.128:61616");
		
		try {
			connection = factory.createConnection();
			
			connection.start();
			
			session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
			
			destination= session.createQueue("first-listener");
			
			producer = session.createProducer(destination);
			// 发送50条消息到队列中
			for(int i = 0; i < 50; i++) {
				textMessage = session.createTextMessage(message + " " + i);
				producer.send(textMessage);
			}
			System.out.println("消息已发送!");
		} catch (JMSException e) {
			e.printStackTrace();
		} finally {
			try {
				connection.close();
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		PTP_Producer_Listener p = new PTP_Producer_Listener();
		p.sendMessage("hello world!");
	}
}
Consumer
  • 代码
public class PTP_Consumer_Listener {
	// 连接工厂
	private ConnectionFactory factory = null;
	// 连接
	private Connection connection = null;
	// 会话
	private Session session = null;
	// 消费者
	private MessageConsumer consumer = null;
	// 目的地
	private Destination destination = null;
	// 消息
	private TextMessage textMessage = null;

	private void receive() {
		factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.65.128:61616");
		
		try {
			connection = factory.createConnection();
			
			connection.start();
			// 设置确认消息方式为客户端确认
			session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
			
			destination = session.createQueue("first-listener");
			
			consumer = session.createConsumer(destination);
			/**
			 * 设置消息监听器,当队列中有新消息时,会自动执行onMessage方法
			 */
			consumer.setMessageListener(new MessageListener() {
				@Override
				public void onMessage(Message message) {
					// 确认消息
					try {
						message.acknowledge();
						textMessage  = (TextMessage) message;
						String text = textMessage.getText();
						System.out.println(text);
					} catch (JMSException e) {
						e.printStackTrace();
					}
				}
			});
			// 阻塞,保证程序不会结束运行,监听不关闭
			try {
				System.in.read();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (JMSException e) {
			e.printStackTrace();
		} finally {
			try {
				connection.close();
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		PTP_Consumer_Listener c = new PTP_Consumer_Listener();
		c.receive();
	}
}
运行结果

运行前,先启动两个consumer,再由producer发送50条消息到Queue中,观察结果。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

可以看到,两个consumer交替从队列中取出消息。

Publish & Subscribe处理模式(Topic)

和PTP模式不同,发布到topic中的消息被所有订阅该topic的订阅者消费。当生产者发布消息时,无论有无消费者,topic都不做保留,无消费者时直接丢弃消息。所以,一定要先有消费者,后有生产者。

Producer
  • 代码
public class Topic_Producer {
	// 连接工厂
	private ConnectionFactory factory = null;
	// 连接
	private Connection connection = null;
	// 会话
	private Session session = null;
	// 目的地
	private Destination destination = null;
	// 生产者
	private MessageProducer producer = null;
	// 消息
	private TextMessage textMessage = null;
	
	private void sendMessage(String message) {
		factory = new ActiveMQConnectionFactory("admin", "admin","tcp://192.168.65.128:61616");
		
		try {
			connection = factory.createConnection();
			
			connection.start();
			
			session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			
			destination = session.createTopic("first-topic");
			
			producer = session.createProducer(destination);
			
			textMessage = session.createTextMessage(message);
			
			producer.send(textMessage);
			
			System.out.println("消息已发送!");
		} catch (JMSException e) {
			e.printStackTrace();
		} finally{
			try {
				connection.close();
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		Topic_Producer p = new Topic_Producer();
		p.sendMessage("this is a broadcast message!");
	}
}
Consumer
  • 代码
public class Topic_Consumer {
	// 连接工厂
	private ConnectionFactory factory = null;
	// 连接
	private Connection connection = null;
	// 会话
	private Session session = null;
	// 目的地
	private Destination destination = null;
	// 生产者
	private MessageConsumer consumer = null;
	// 消息
	private TextMessage textMessage = null;
	
	private void receive() {
		factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.65.128:61616");
		
		try {
			connection = factory.createConnection();
			
			connection.start();
			
			session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			
			destination = session.createTopic("first-topic");
			
			consumer = session.createConsumer(destination);
			
			textMessage = (TextMessage) consumer.receive();
			
			String text = textMessage.getText();
			
			System.out.println(text);
		} catch (JMSException e) {
			e.printStackTrace();
		} finally {
			try {
				connection.close();
			} catch (JMSException e) {
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		Topic_Consumer c = new Topic_Consumer();
		c.receive();
	}
}
运行结果

先启动了3个consumer,接着启动producer发送消息。

在这里插入图片描述

结果显示,3个consumer都接收到了producer发送的消息。

安全认证

即用户名、密码登录规则,需要再核心配置中开启安全认证,即conf/acticemq.xmlbroker标签。

第一步:开启安全认证

<broker>标签中添加<plugins>标签

标签作用对应文件
<plugins>配置安全认证信息
<jaasAuthenticationPlugin configuration="activemq" />添加 jaas 认证插件,activemq 在 login.config 里面定义login.config
<authorizationPlugin> <map> <authorizationMap> <authorizationEntries>中间</authorizationEntries> </authorizationMap> </map> </authorizationPlugin>层层嵌套,最中间添加详细配置
<authorizationEntry topic="名字" read="用户组名" write="用户组名" admin="用户组名" />配置需要进行安全验证的topic,名字为“>”是代表全部users.propertiesgroups.properties
<authorizationEntry queue="名字" read="用户组名" write="用户组名" admin="用户组名" />配置需要进行安全验证的queue,名字为“>”是代表全部users.propertiesgroups.properties
<authorizationEntry topic="ActiveMQ.Advisory.>" read="admins" write="admins" admin="admins"/>这个必须配置,不能少!
<authorizationEntry queue="ActiveMQ.Advisory.>" read="admins" write="admins" admin="admins"/>这个必须配置,不能少!
<plugins>
 	<!-- use JAAS to authenticate using the login.config file on the classpath to configure JAAS --> 
 	<!-- 添加 jaas 认证插件 activemq 在 login.config 里面定义,详细见 login.config-->
	<jaasAuthenticationPlugin configuration="activemq" /> 
	<authorizationPlugin>
		 <map>
			 <authorizationMap> 
				 <authorizationEntries> 
					 <authorizationEntry topic=">" read="admins" write="admins" admin="admins" /> 
					 <authorizationEntry queue=">" read="admins" write="admins" admin="admins" /> 
					 <authorizationEntry topic="ActiveMQ.Advisory.>" read="admins" write="admins" admin="admins"/> 
					 <authorizationEntry queue="ActiveMQ.Advisory.>" read="admins" write="admins" admin="admins"/> 
				 </authorizationEntries> 
			 </authorizationMap> 
		 </map>
	  </authorizationPlugin> 
</plugins>

在这里插入图片描述

  • login.config
    在这里插入图片描述
第二步:提供用户名、密码
  • users.properties

格式:
用户名=密码

在这里插入图片描述

第三步:提供用户组信息
  • group.properties

格式:
用户组名=用户名,用户名,。。。。

在这里插入图片描述

重新启动activemq服务即可
  • 这时,在创建ConnectionFactory是,需要如果访问某个设置了安全认证的topic或者queue,需要输入对应用户组中存在的用户名和密码,正确后才可访问!!!

持久化策略

指对消息数据的持久化,在ActiveMQ中,默认的消息是保存在内存中的,当内存容量不足,或ActiveMQ正常关闭的时候,会将内存中未处理的消息持久化到磁盘中,具体的持久化策略有配置文件中的具体配置决定。
持久化配置在conf/activemq.xml该配置文件中,使用<broker>标签定义。

kahadb方式(默认)
  • 特点:

① 日志形式存储数据;
② 消息索引以B-Tree结构存储,可以快速更新;
③ 完全支持KMS事务;
④ 支持多种恢复机制;

  • 配置
<persistenceAdapter>
	<!-- directory: 保存数据的目录
		journalMaxFileLength:保存消息的文件大小,每个文件
	-->
	<kahaDB directory="${activemq.data}/kahadb" journalMaxFileLegth="16mb"/>
</persistenceAdapter>

在这里插入图片描述

  • 测试

① 先往队列中发送一条消息,如:“hello”;
② 不消费消息,关闭activemq服务;
③ 再次启动activemq服务,可看到消息还在队列中,取出消息;

JDBC+MySQL持久化
配置步骤

第一步:在activemq.xml中创建数据源

<bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
	 <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 		
	 <property name="url" value="jdbc:mysql://localhost:3306/activemq?relaxAutoCommit=true"/> 
	 <property name="username" value="activemq"/> 
	 <property name="password" value="activemq"/> 
	 <property name="maxActive" value="200"/> 
	 <property name="poolPreparedStatements" value="true"/>
</bean>

第二步:在<broker>标签中配置mysql持久化

<persistenceAdapter> 
	<jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="false"/> 
</persistenceAdapter>

第三步:将mysql的驱动包放入activemq的lib目录下,注意jdk版本哈,深坑,勿爬!

注意

ActiveMQ可自动创建表格,但是不能创建数据库。
createTablesOnStartup默认为true,一般是第一次启动为true,之后修改为false,否则之前持久化的数据会被删除!!!

图示:

在这里插入图片描述
在这里插入图片描述

当第一次启动后,会自动创建3个表,查看数据库:
在这里插入图片描述

这时,要记得将createTablesOnStartup中的true改成false!!!
在这里插入图片描述

我们发送一条消息:
在这里插入图片描述
查看数据库:
在这里插入图片描述
数据已经持久化到数据库中

这时我们将这条消息消费掉:
在这里插入图片描述
数据库中的消息被删除!

主从模型

主从模式是一种高可用解决方案。在 ZooKeeper 中注册若干 ActiveMQ Broker,其中只 有一个 Broker 提供对外服务(Master),其他 Broker 处于待机状态(Slave)。当 Master 出现 故障导致宕机时,通过 ZooKeeper 内部的选举机制,选举出一台 Slave 替代 Master 继续对外 提供服务。

安装Zookeeper

ActiveMQ集群依赖于Zookeeper

下载并解压

我这里使用的是zookeeper-3.4.6这个版本。

配置Zookeeper

在本机搭建伪集群,安装三个Zookeeper实例,使用不同端口实现同时开启。端口分配如下:

主机服务端口投票端口选举端口
192.168.65.128218128813881
192.168.65.128218228823882
192.168.65.128218328833883
步骤
  • ①修改名称:zk_01(可不修改)

mv zookeeper-3.4.6 zk_01

  • ②在zk_01中创建data数据目录

mkdir data

  • ③为zookeeper增加服务命名

在data目录中增加文件myid,内部定义每个服务的编号,编号要求为数字,是正整数,使用回声命名快捷定义myid文件:
echo 1 >> myid
在这里插入图片描述

  • ④创建zookeeper配置文件

zookeeper默认读取conf/zoo.cfg配置文件,但是只提供给我们一个zoo_simple.cfg文件,所以我们复制一份到zoo.cfg

  • ⑤编写Zookeeper配置文件

1、修改数据目录为data目录
2、修改服务端口
3、配置集群,提供多节点服务:server.编号=IP:投票端口:选举端口,三个zookeeper此应用配置一致;
在这里插入图片描述

  • ⑥将zk_01复制三份,重复第⑤步,依次修改对应的服务编号、data目录和服务端口

在这里插入图片描述

  • ⑦启动

命令:bin/zkServer.sh start
在这里插入图片描述

观察主从

当启动完毕后,怎么判断哪个是主机哪个是从机呢?
命令:/bin/zkServer.sh status
从机:在这里插入图片描述
主机:
在这里插入图片描述

访问

命令:bin/zkCli.sh

ActiveMQ主从搭建

搭建ActiveMQ伪集群,安装三个实例,使用不同端口实现同时启动,端口分配如下:

主机M-S通讯端口服务端口jetty端口
192.168.65.12862626616168161
192.168.65.12862627616178162
192.168.65.12862628616188163
步骤
  • ①将activemq复制三份,分别命名为mq_1、mq-2、mq_3

这里是引用

  • ②修改jetty端口,conf/jetty.xml

端口分别是:8161、8162、8163
在这里插入图片描述

  • ③统一所有主从节点broker命名,conf/activemq.xml

修改<broker>标签属性brokerName="统一名称"
在这里插入图片描述

  • ③修改持久化配置,conf/activemq.xml

修改<broker>标签中的<persistenceAdapter>相关内容:

属性含义
replicas代表当前主从模型中的节点数量
bindbind 属性中的端口为主从实例之间的通讯端口。代表当前实例对外开放端口是什么,三 个实例分别使用 62626、62627、62628 端口。
zkAddress代表 ZooKeeper 安装位置,安装具体情况设置
zkPath是 ActiveMQ 主从信息保存到 ZooKeeper 中的什么目录内
hostname为 ActiveMQ 实例安装 Linux 的主机名,可以在/etc/hosts 配置文件中设置。设 置格式为:IP 主机名。 如: 127.0.0.1 mq-server。这里需要修改主机名
<persistenceAdapter> 
	<!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
	 <replicatedLevelDB
                        directory="${activemq.data}/levelDB"
                        replicas="3"
                        bind="tcp://0.0.0.0:62626"
                        zkAddress="192.168.65.128:2181,192.168.65.128:2182,192.168.65.128:2183"
                        zkPath="/activemq/leveldb-stores"
                        hostname="mq-server"
                />
</persistenceAdapter>

在这里插入图片描述

  • ④修改主机名,etc/hosts

在/etc/hosts 配置文件中设置。设 置格式为:IP 主机名。 如: 127.0.0.1 mq-server
修改完成:ping mq-server

  • ⑤修改ActiveMQ对外提供服务的端口,conf/activemq.xml

默认为61616,这里使用的是61616、61617、61618,依次做修改。修改<broker>标签的子标签<transportConnectors>内容即可。
在这里插入图片描述

  • ⑥启动主从

命令:bin/activemq start
可通过jps查看
在这里插入图片描述

  • ⑦查看主从状态

使用客户端连接zookeeper:${zkHome}/bin/zkCli.sh


查看状态信息:
连接成功后,可以使用命令ls /查看 ZooKeeper 中的目录结构;


ls /activemq/leveldb-stores 找到对应的内容后,可以使用命令get查看 ZooKeeper 中的数据内容
在这里插入图片描述


其中主节点的 elected 及 address 属性一定有数据。从节点则数据为‘null’。


主节点:
在这里插入图片描述


从节点:
在这里插入图片描述

  • ⑧使用jetty访问时,只有主机的控制台可以访问,从机是不可访问的,只有等主机宕机后,由zookeeper投票选出主机后,那台主机的jetty控制台才可以被访问。
java访问主从
factory = new ActiveMQConnectionFactory("admin", "admin", 
		"failover:(tcp://192.168.65.128:61616,
				tcp://192.168.65.128:61617,
				tcp://192.168.65.128:61618)");

集群

准备多份主从模型。在所有的 ActiveMQ 节点中的 conf/activemq.xml 中增加下述配置: (每个主从模型中的 networkConnector 都指向另外一个主从模型)

<networkConnectors>
	 <networkConnector uri="static://(tcp://ip:port,tcp://ip:port)" duplex="false"> 
	 </networkConnector> 
</networkConnectors>

注意配置顺序,Networks 相关配置必须在持久化相关配置之前。如下:

<?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://activemq.apache.org/schema/core"> 
 	<broker xmlns="http://activemq.apache.org/schema/core" brokerName="mq-cluster" dataDirectory="${activemq.data}" > 
 		<networkConnectors> 
 			<networkConnector uri=" static://(tcp://ip:port,tcp://ip:port)"/>
 		 </networkConnectors>
 		 
 	  	<persistenceAdapter> 
 	  		< replicatedLevelDB directory = "xxx"/> 
 	 	 </persistenceAdapter> 
	</broker> 
</beans>

Spring整合ActiveMQ

生产者
  • 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 配置ActiveMQ连接工厂信息 -->
	<bean id="factory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="userName" value="admin"/>
		<property name="password" value="admin"/>
		<property name="brokerURL" value="tcp://192.168.65.128:61616"/>
	</bean>
	<!-- spring接管ActiveMQ连接工厂,产生jms连接工厂 -->
	<bean id="jmsFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
		<property name="targetConnectionFactory" ref="factory"/>
	</bean>
	<!-- 配置生产者 -->
	<!-- 配置spring提供的模板JMSTepleate-->
	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="jmsFactory"/>
	</bean>
	<!-- 配置队列目的地-->
	<bean id="myQueue" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg>
			<value>
				queue
			</value>
		</constructor-arg>
	</bean>
	<!-- 配置主题目的地 -->
	<bean id="myTopic" class="org.apache.activemq.command.ActiveMQTempTopic">
		<constructor-arg>
			<value>
				topic
			</value>
		</constructor-arg>
	</bean>
</beans>
  • 测试代码
public class Producer {
	public static void main(String[] args) {
		// 初始化spring容器
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext_producer.xml");
		// 从spring容器中获取JMSTemplate
		JmsTemplate template = ctx.getBean("jmsTemplate", JmsTemplate.class);
		// 从spring容器中获取目的对象
		Destination destination = ctx.getBean("myQueue", Destination.class);
		// 发送消息
		template.send(destination, new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				TextMessage textMessage = session.createTextMessage("test spring-activemq");
				return textMessage;
			}
		});
		System.out.println("消息已发送");
	}
}
消费者
  • 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 配置ActiveMQ连接工厂信息 -->
	<bean id="factory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="userName" value="admin"/>
		<property name="password" value="admin"/>
		<property name="brokerURL" value="tcp://192.168.65.128:61616"/>
	</bean>
	<!-- spring接管ActiveMQ连接工厂,产生jms连接工厂 -->
	<bean id="jmsFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
		<property name="targetConnectionFactory" ref="factory"/>
	</bean>
	<!-- 配置消费者 -->
	<!-- 配置spring提供的模板JMSTepleate-->
	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="jmsFactory"/>
	</bean>
	<!-- 配置队列目的地-->
	<bean id="myQueue" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg>
			<value>
				queue
			</value>
		</constructor-arg>
	</bean>
	<!-- 配置主题目的地 -->
	<bean id="myTopic" class="org.apache.activemq.command.ActiveMQTempTopic">
		<constructor-arg>
			<value>
				topic
			</value>
		</constructor-arg>
	</bean>
	<!-- 开启,配置消息监听器 -->
	<!-- <bean id="listener" class="testConsumer.ConsumerListener"></bean> -->
	<!-- 监听容器 -->
	<!-- <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="connectionFactory" ref="jmsFactory"></property>
		<property name="destination" ref="myQueue"></property>
		<property name="messageListener" ref="listener"></property>
	</bean> -->
</beans>
  • 测试类
public class Consumer {
	public static void main(String[] args) {
		// 初始化spring容器
		ApplicationContext ctx =
			    new ClassPathXmlApplicationContext("classpath:applicationContext_consumer.xml");
		// 无监听获取消息
		method_noListener(ctx);
		
		// 阻塞监听
		try {
			System.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void method_noListener(ApplicationContext ctx) {
		// 从spring容器中获取JMSTemplate
		JmsTemplate template = ctx.getBean("jmsTemplate", JmsTemplate.class);
		// 从spring容器中获取目的对象
		Destination destination = ctx.getBean("myQueue", Destination.class);
		// 接收消息
		Message message = template.receive(destination);
		TextMessage textMessage = (TextMessage) message;
		try {
			String text = textMessage.getText();
			System.out.println(text);
		} catch (JMSException e1) {
			e1.printStackTrace();
		}
	}
}
  • 如果开启了监听,需要一个监听器类
public class ConsumerListener implements MessageListener{

	public void onMessage(Message message) {
		TextMessage tm = (TextMessage) message;
		try {
			String text = tm.getText();
			System.out.println("收到消息: "+text);
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值