前言
体能状态先于精神状态,习惯先于决心,聚焦先于喜好。
往期回顾
ActiveMQ 的系列文章已经搁置很久没有继续了,https://blog.youkuaiyun.com/bestcxx/column/info/23061
之前已经测试了queue类型和topic类型的消息的发送和接收,但是接收是同步的,就是会阻塞线程,今天介绍的监听器容器会在消息达到MQ时自动将消息传递到我们指定的方法中执行。更进一步来说,我们还没有讨论消息的确认机制和事务,这两个我们现在依旧先不讨论。
化繁为简的表述
之前文章的表述处于起步阶段,所以难免繁琐,本篇将绝大多数的Spring bean 的声明使用 @Bean 标签进行声明,放到了一个配置类,读者直接看注释即可。
监听器容器
由 Spring 提供,一共有三个
DefaultMessageListenerContainer只是其中一种,支持事务。
另外还有 不支持事务的 SimpleMessageListenerContainer
和 支持事务和动态会话管理的 ListertenerContainer
本文使用 DefaultMessageListenerContainer,
代码
自定义监听器
监听器是处理消息的具体类
package com.bestcxx.stu.jms.activemq;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
/**
* 自定义监听器实现
*/
public class MyMessageListener implements MessageListener {
@Override
public void onMessage(Message message){
try{
TextMessage m=(TextMessage) message;
System.out.println("msg="+m.getText());
}catch(Exception e){
System.out.println(e);
}
}
}
Bean 集合:各位看注释
重点是我们定义了 MQ 连接工厂、MQ连接工厂池、JmsTempalte 、ActiveMQ queue、自定义监听器以及监听器容器 这些Spring Bean
本文只列举了监听器容器监听 queue 类型的消息,对于 topic 类型的消息处理流程是一样的
package com.bestcxx.stu.jms.activemq;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.pool.PooledConnectionFactory;
import org.apache.activemq.spring.ActiveMQConnectionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
/**
* ActiveMQ 相关 Spring Bean 声明
*/
@Configuration
public class ActiveMQConfigBean {
/**连接工厂*/
@Bean(name="activeMQConnectionFactory")
public ActiveMQConnectionFactory getActiveMQConnectionFactory(){
ActiveMQConnectionFactory a=new ActiveMQConnectionFactory();
a.setBrokerURL("tcp://localhost:61616");//我本地已启动 ActiveMQ
a.setTrustAllPackages(true);
return a;
}
/**连接工厂池*/
@Bean(name="pooledConnectionFactory")
public PooledConnectionFactory getPooledConnectionFactory(){
PooledConnectionFactory p=new PooledConnectionFactory();
p.setConnectionFactory(getActiveMQConnectionFactory());
p.setMaxConnections(1);//设置最大连接数
//其他更多配置略
return p;
}
/**Spring JmsTemplate*/
@Bean(name="JmsTemplate")
public JmsTemplate getJmsTemplateTopic(){
JmsTemplate j=new JmsTemplate();
j.setConnectionFactory(getPooledConnectionFactory());//连接工厂
return j;
}
/**ActiveMQ Queue*/
@Bean(name="activeMQQueue")
public ActiveMQQueue getActiveMQQueue(){
ActiveMQQueue a=new ActiveMQQueue("queue_test");//构造方法同时确定来主题消息的名字
return a;
}
/**自定义消息监听器bean*/
@Bean(name="myMessageListener")
public MyMessageListener getMyMessageListener(){
MyMessageListener m=new MyMessageListener();
return m;
}
/**
* 注册监听器容器
* DefaultMessageListenerContainer只是其中一种,支持事务
* 另外还有 不支持事务的 SimpleMessageListenerContainer
* 和 支持事务和动态会话管理的 ListertenerContainer
* */
@Bean(name="defaultMessageListenerContainer")
public DefaultMessageListenerContainer getDefaultMessageListenerContainer(){
DefaultMessageListenerContainer d=new DefaultMessageListenerContainer();
d.setConnectionFactory(getPooledConnectionFactory());
d.setDestination(getActiveMQQueue());
d.setMessageListener(getMyMessageListener());
return d;
}
}
xml 配置文件
@Bean 标签和@Configuration标签极大的简化了xml文件的配置工作
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
">
<context:component-scan base-package="com.bestcxx.stu.jms.activemq"/>
</beans>
测试类
testSend 发送消息到 queue,并会触发监听器容器,将消息转交给自定义监听器,
testReceive 方法是为了便于对比阻塞和非阻塞。
package com.bestcxx.stu.jms.activemq;
import org.apache.activemq.command.ActiveMQQueue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
@DirtiesContext
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:test/applicationContext-activemq.xml"})
//@TransactionConfiguration(transactionManager = "defaultTransactionManager",defaultRollback=false)//事务管理
@Rollback(true)
public class ActiveMQConfigBeanTest {
@Resource(name="JmsTemplate")
private JmsTemplate jmsTemplate;
@Resource(name="activeMQQueue")
private ActiveMQQueue activeMQQueue;
@Test
public void testSend(){
jmsTemplate.setDefaultDestination(activeMQQueue);
// jmsTemplate.convertAndSend("你好");
jmsTemplate.send(new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
System.out.println(session.getAcknowledgeMode());
return session.createTextMessage("hello");
}
});
try{
Thread.sleep(5000);
}catch(Exception e){
}
}
@Test
public void testReceive(){
jmsTemplate.setDefaultDestination(activeMQQueue);
jmsTemplate.setSessionTransacted(true);
String str=(String)jmsTemplate.receiveAndConvert();
System.out.println("str="+str);
}
}
本文详细介绍如何使用Spring提供的DefaultMessageListenerContainer处理ActiveMQ的队列消息,通过自定义监听器实现非阻塞的消息接收,简化了XML配置,提供了代码示例及测试方法。
1810

被折叠的 条评论
为什么被折叠?



