ActiveMQ 与 Spring
1. ActiveMQ安装
1.1 下载(版本5.14.5)
1.2 安装
解压下载的压缩文件到任意目录中(
eg. C:\Program Files (x86)\apache-activemq-5.14.5),进入%ACTIVEMQ_HOME%/bin目录,根据自己的系统位数,进入32/64目录,点击activemq.bat启动ActiveMQ;
2. ActiveMQ与Spring整合使用
2.1 在Maven中添加ActiveMQ和JMS相关的pom,如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.2.5.RELEASE</version>
<!--<version>{spring.version}</version>-->
</dependency>
<!-- xbean 如<amq:connectionFactory /> -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.12.1</version>
</dependency>复制代码
2.2 添加配置文件spring-activemq.xml
在配置文件中加入以下配置信息,每个配置信息都有具体的解释:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd">
<!--配置连接ActiveMQ的连接基本信息 -->
<amq:connectionFactory id="amqConnectionFactory"
brokerURL="tcp://localhost:61616" userName="admin" password="admin" />
<!-- 配置JMS连接工厂 -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="amqConnectionFactory" />
<property name="sessionCacheSize" value="100" />
</bean>
<!-- 定义消息队列(Queue) -->
<bean id="demoQueueDestination" class="org.apache.activemq.command.ActiveMQQueue">
<!-- 设置消息队列的名字 -->
<constructor-arg>
<value>testQueue</value>
</constructor-arg>
</bean>
<!-- 配置JMS模板(Queue),Spring提供的JMS工具类,它发送、接收消息。 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="defaultDestination" ref="demoQueueDestination" />
<property name="receiveTimeout" value="10000" />
<!-- true是topic,false是queue,默认是false -->
<property name="pubSubDomain" value="false" />
</bean>
<!-- 配置消息队列监听者(Queue) -->
<!-- 打开监听器,会立即去消费消息(即,起到实时消费通信的作用) -->
<!-- <bean id="queueMessageListener" class="com.hp.common.listener.QueueMessageListener"></bean> -->
<!-- 显示注入消息监听容器(Queue),配置连接工厂,监听的目标是demoQueueDestination,监听器是上面定义的监听器 -->
<!-- <bean id="queueListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="demoQueueDestination" />
<property name="messageListener" ref="queueMessageListener" />
</bean>
-->
</beans>复制代码
注:在配置文件中,一定不要忘记加入ActiveMQ和JMS相关的schema
2.3 创建Producer和Consumer相关的Service
创建ProducerService,用于发送信息到消息中心
@Service
public class ProducerService {
@Resource(name = "jmsTemplate")
private JmsTemplate jmsTemplate;
private Queue queue;
/**
* 根据目的地发送消息
*/
public void sendMessage(Destination destination, final String msg) {
System.out.println(Thread.currentThread().getName() + " 向队列" + destination.toString()
+ "发送消息------->" + msg);
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(msg);
}
});
}
public String send(String userId, String msg) {
System.out.println(
Thread.currentThread().getName() + " 向 " + userId + " 的队列" + userId.toString() + "发送消息------>" + msg);
queue = new ActiveMQQueue(userId);
jmsTemplate.send(queue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage message=session.createTextMessage(msg);
message.setStringProperty(userId, msg);
return message;
}
});
return "发送成功";
}
/**
* 向默认目的地发送消息
*/
public String sendMessage(final String msg) {
String destination = jmsTemplate.getDefaultDestinationName();
System.out
.println(Thread.currentThread().getName() + " 向队列" + destination + "发送消息---------------------->" + msg);
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(msg);
}
});
return "发送成功";
}
}复制代码
创建ConsumerService,用于接受消息
@Service
public class ConsumerService{
@Resource(name = "jmsTemplate")
private JmsTemplate jmsTemplate;
public String receive(Destination destination) {
TextMessage textMessage = (TextMessage) jmsTemplate.receive(destination);
try {
System.out.println("从队列" + destination.toString() + "收到了消息:\t" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
return textMessage.toString();
}
public String receive(String userId) {
Queue queue=new ActiveMQQueue(userId+"?consumer.prefetchSize=4");
Message message = null;
String property=null;
try {
message=jmsTemplate.receive(queue);
property=message.getStringProperty(userId);
System.out.println("从队列" + queue.toString() + "收到了消息:\t" + property);
} catch (JMSException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return property;
}
}复制代码
2.4 添加Controller,用于曝露接口
@Controller
@RequestMapping(value="/mq")
public class MessageController {
private Logger logger = Logger.getLogger(MessageController.class);
@Resource(name = "demoQueueDestination")
private Destination destination;
@Autowired
private ProducerService producer;
@Autowired
private ConsumerService consumer;
@RequestMapping(value = "/SendMessage", method = RequestMethod.POST,produces="application/json")
@ResponseBody
public void send(@RequestParam(value = "userId",required=false)String userId,@RequestParam(value = "msg")String msg) {
logger.info(Thread.currentThread().getName() + "------------send to jms Start");
if (userId==null||"".equals(userId)) {
producer.sendMessage(destination, msg);
}else {
producer.send(userId, msg);
}
logger.info(Thread.currentThread().getName() + "------------send to jms End");
}
@RequestMapping(value = "/ReceiveMessage", method = RequestMethod.GET)
@ResponseBody
public Object receive(@RequestParam(value = "userId",required=false)String userId) {
logger.info(Thread.currentThread().getName() + "------------receive from jms Start");
String tm=null;
if (userId==null||"".equals(userId)) {
tm = consumer.receive(destination);
} else {
tm = consumer.receive(userId);
}
logger.info(Thread.currentThread().getName() + "------------receive from jms End");
return tm.toString();
}
}复制代码
2.5 配置监听器(ek)
如果在配置文件中打开了监听器的注释,即打开监听器,消费者会立即去消费消息,则还需要添加如下代码:
public class QueueMessageListener implements MessageListener{
@Override
public void onMessage(Message message) {
TextMessage tm=(TextMessage) message;
try {
System.out.println("QueueMessageListener监听到了文本消息:\t"
+ tm.getText());
//do other work
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}复制代码
3. 测试
启动tomcat,将Javaweb项目运行在tomcat中,通过postman测试接口和方法
接受消息接口:http://localhost:8080/`{project_neme}`/mq/ReceiveMessage?userId={消息队列名称}
发送消息接口:http://localhost:8080/`{project_neme}`/mq/SendMessage?userId={消息队列名称}&msg={参数}
4. 其他场景及技术应用
场景1: 对于mq队列中的消息,系统需要做一些监控或者问题的跟踪,则需要去查看MQ中的数据,但是有需要保证在查看之后不会被删除,因为在P2P模式中,consumer.receive()后消息之后,消息就被消费,MQ不会发送其他consumer,对于这种场景该如何考虑采用ActiveMQ的何种技术去做?
场景2:将使用JDBC持久化的ActiveMQ转换为其他存储方式(文件存储、Kaha、memory),需要做数据迁移,那如何实现?
解决:对于这两种场景,都可以用消息队列中消息查看的方式去实现;
第一个场景,使用ActiveMQ的Browser可以查看未被消费的信息,这样既保证数据不会被消费,也可以实现自己的其他业务;
第二个场景,可以使用Browser将未被消费的信息拿出来,然后再通过produce.send()的方式,将消息发送到其他存储方式的ActiveMQ上;
以下代码实现了使用Browser读出某个队列中未消费的所有消息,并将它们放到list中
public class BrowersService {
private static final Logger logger=LogManager.getLogger(BrowersService.class);
//配置文件配置的jmsTemplate
@Resource(name = "jmsTemplate")
private JmsTemplate jmsTemplate;
public void getMessageFromQuese(String queueName){
List<String> message=jmsTemplate.browse(queueName, new BrowserCallback<List<String>>() {
@Override
public List<String> doInJms(Session session, QueueBrowser browser) throws JMSException {
Enumeration<TextMessage> enumeration=browser.getEnumeration();
List<String> messages=new ArrayList<>();
while (enumeration.hasMoreElements()) {
TextMessage textMessage = (TextMessage) enumeration.nextElement();
logger.info("Message text: "+ textMessage.getText()
+" ID: "+textMessage.getJMSMessageID());
messages.add(textMessage.getText());
}
return messages;
}
});
logger.info("message from browser "+message);
}
}
ActiveMQ 与 Spring的更多相关文章
- ActiveMQ与spring整合
第一步:引用相关的jar包 <dependency> <groupId>org.springframework</groupId> <artifactId&g ...
- activeMQ和spring的整合
http://www.cnblogs.com/shuai-server/p/8966299.html 这篇博客中介绍了activemq传递消息的两种方式,今天分享的是activemq框架和sprin ...
- ActiveMQ集成Spring使用
现在任何一个框架的使用都会结合spring框架,quartz.cxf与平时常见的Hibernate.mybatis.Struts等都可以与spring集成起来使用,在这里研究了activemq结合sp ...
- ActiveMQ整合spring、同步索引库
1. Activemq整合spring 1.1. 使用方法 第一步:引用相关的jar包. <dependency> <groupId>org.springframework ...
- JAVAEE——宜立方商城09:Activemq整合spring的应用场景、添加商品同步索引库、商品详情页面动态展示与使用缓存
1. 学习计划 1.Activemq整合spring的应用场景 2.添加商品同步索引库 3.商品详情页面动态展示 4.展示详情页面使用缓存 2. Activemq整合spring 2.1. 使用方法 ...
- activeMQ的spring、springboot的DEMO
一.activeMQ实现spring的demo 1:pom.xml文件 <dependencies> <dependency> <groupId>junit< ...
- 淘淘商城项目_同步索引库问题分析 + ActiveMQ介绍/安装/使用 + ActiveMQ整合spring + 使用ActiveMQ实现添加商品后同步索引库_匠心笔记
文章目录 1.同步索引库问题分析 2.ActiveM的介绍 2.1.什么是ActiveMQ 2.2.ActiveMQ的消息形式 3.ActiveMQ的安装 3.1.安装环境 3.2.安装步骤 4.Ac ...
- ActiveMQ学习笔记(6)----ActiveMQ整合Spring开发
1. 添加依赖 spring 提供了对JMS的支持,需要添加Spring支持jms的包和Spring的核心包,如下: <dependency> <groupId>org.apa ...
- 分布式-信息方式-ActiveMQ结合Spring
ActiveMQ结合 Spring开发■ Spring提供了对JMS的支持,需要添加 Spring支持jms的包,如下: <dependency> <groupId>org.a ...
随机推荐
- 使用命令virsh管理网络设备,创建桥设备 和 使用virt-manager创建虚拟机
# 1:查看网卡接口 virsh iface-list Name State MAC Address ------------------------------------------------- ...
- HttpHandler与HttpModule的理解与应用
问题1:什么是HttpHandler? 问题2:什么是HttpModule? 问题3:什么时候应该使用HttpHandler什么时候使用HttpModule? 答案1:HttpHandler,Http ...
- SPOJ3899——Finding Fractions
SPOJ上的每个题目都做得我泪牛满面. 这个题目也是的.题目意思是给你两个分数a/b和c/d,要你求出一个分数p/q,使得a/b<p/q<c/d,且p最小. 看完题目后半天都没有任何思路哦 ...
- 对Spark2.2.0文档的学习3-Spark Programming Guide
Spark Programming Guide Link:http://spark.apache.org/docs/2.2.0/rdd-programming-guide.html 每个Spark A ...
- BZOJ 2957 楼房重建(线段树区间合并)
一个显而易见的结论是,这种数字的值是单调递增的.我们修改一个数只会对这个数后面的数造成影响.考虑线段树划分出来的若干线段. 这里有两种情况: 1.某个线段中的最大值小于等于修改的数,那么这个线段的贡献 ...
- 【bzoj3119】Book 数学
题目描述 一个长度为N的序列的首项为X,以后的每一项要么比前一项大A,要么比前一项小B.已知总和为M,求一组可行方案. 输入 第一行一个正整数N.第二行四个整数依次是X,A,B,M. 输出 输出一行N ...
- 【uoj#174】新年的破栈 贪心
题目描述 给你一个长度为 $n$ 的序列和一个空的双端队列,每次进行3种操作种的一种: 1.将序列中编号最小的数加入到双端队列的队尾:2.从双端队列的队尾取出一个数:3.从双端队列的队头取出一个数. ...
- Mybatis笔记四:Mybatis中的resultType和resultMap查询操作实例详解
resultType和resultMap只能有一个成立,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,resultMap解决复杂查询是的映射问题.比 ...
- 流媒体协议之RTSP客户端的实现20171014
RtspClient是基于jrtplib实现的,目前仅支持h264格式,后续将不断迭代优化,加入对其他格式的支持,并且将实现RTSP的服务端. RtspClient的功能是接收服务端过来流,然后写入到 ...
- winform登录代码
Program.cs文件中 static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThr ...