2.5、 使用监听器容器自动获取 ActiveMQ中的消息

本文详细介绍如何使用Spring提供的DefaultMessageListenerContainer处理ActiveMQ的队列消息,通过自定义监听器实现非阻塞的消息接收,简化了XML配置,提供了代码示例及测试方法。

前言

体能状态先于精神状态,习惯先于决心,聚焦先于喜好。

往期回顾

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);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值