Spring 整合 ActiveMQ

本机环境

Win10 64位
Spring 4.3.12
ActiveMQ 5.15.5

ActiveMQ安装

http://activemq.apache.org/
1. 下载对应文件解压后执行对应操作系统的activemq.bat
2. 打开浏览器进入 http://localhost:8161/admin/
3. 看到内容就说明ActiveMQ服务已启动 (用户名&密码默认为admin)

spring + ActiveMQ

pom.xml 配置

引入如下的包

    <!-- spring整合消息队列activemq -->
        <!-- 要和自己下的activemq版本对应 -->
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-spring</artifactId>
            <version>5.15.5</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- 这个不知道干啥的,反正不加会报错! -->
        <dependency>
            <groupId>org.apache.xbean</groupId>
            <artifactId>xbean-spring</artifactId>
            <version>4.5</version>
        </dependency>
spring-applicationContext.xml 配置
<!-- activemq配置 -->
    <bean id="amqConnectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
        <property name="brokerURL" value="${activemq.url}"/>
        <property name="userName" value="${activemq.username}" />
        <property name="password" value="${activemq.password}" />
        <!-- trustedPackages 这个属性定义信任的java包,要使用MQ传对象就要将对象对应的类所在的包加入list,不然会报错 -->
        <property name="trustedPackages">
            <list>
                <value>com.shu.yzy.dto</value>
                <value>java.lang</value>
                <value>java.util</value>
            </list>
        </property>
    </bean>
    <!-- 连接 activemq-->
    <!-- <amq:connectionFactory id="amqConnectionFactory" brokerURL="${activemq.url}" userName="${activemq.username}" password="${activemq.password}"/> -->

    <!-- 这里可以采用连接池的方式连接PooledConnectionFactoryBean -->
    <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
        <!-- 配置连接 -->
        <property name="targetConnectionFactory" ref="amqConnectionFactory"/>
        <!-- 会话的最大连接数 -->
        <property name="sessionCacheSize" value="100"/>
    </bean>

    <!-- 定义消息队列topic类型,queue的方式差不多 topic对应订阅模式-->
    <bean id="topic" class="org.apache.activemq.command.ActiveMQTopic">
        <!-- 定义名称 -->
        <constructor-arg index="0" value="topic"/>
    </bean>

    <!-- 定义消息队列(Queue) queue对应点对点模式-->
    <bean id="demoQueueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <!-- 设置消息队列的名字 -->
        <constructor-arg>
            <value>${activemq.queue}</value>
        </constructor-arg>
    </bean>

    <!-- 配置JMS模板(queue),Spring提供的JMS工具类,它发送、接收消息。 -->
    <!-- 为了测试发送消息,保留jmsTemplate的配置,实际不存在发送,只需要配置监听即可 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="defaultDestination" ref="demoQueueDestination"/>
        <!-- 非pub/sub模型(发布/订阅),true为topic,false为queue --> 
        <property name="pubSubDomain" value="false"/>
    </bean>

    <!-- 显示注入消息监听容器(Queue),配置连接工厂,监听的目标是demoQueueDestination,监听器是上面定义的监听器 -->
    <bean id="seckillMessageListener" class="com.shu.yzy.activemq.SeckillMessageListener"></bean>
    <bean id="queueListenerContainer"
          class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="destination" ref="demoQueueDestination" />
        <!-- 这个是DIY的Listener对象 用于监听队列并消费队列元素 -->
        <property name="messageListener" ref="seckillMessageListener" />
    </bean>

activemq.properties 配置

要注意消息队列的默认服务访问端口是61616 别填上面的后台管理端口8161

activemq.url=tcp://localhost:61616
activemq.username=admin
activemq.password=admin
activemq.queue=seckill

简单实现一下MQ功能

Producer 实现

ProducerService 代码清单

package com.shu.yzy.activemq.service;

import javax.jms.Destination;

import com.shu.yzy.dto.SeckillAction;

/**
 * @author Administrator
 *
 */
public interface MQProducerService {

    /** 发送一个对象到指定的目标(Queue或者Topic)
     * @param destination 目的地
     * @param sa 数据传输对象
     */
    void sendSeckillMessage(Destination destination, final SeckillAction sa);

    /** 发送一个对象到默认的destination 可以通过jmsTemplate自动获取
     * @param sa 数据传输对象
     */
    void sendSeckillMessage(final SeckillAction sa);
}

ProducerServiceImpl 代码清单

package com.shu.yzy.activemq.service.impl;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;

import com.shu.yzy.activemq.service.MQProducerService;
import com.shu.yzy.dto.SeckillAction;

/**
 * @author Administrator
 *
 */
@Service("mqProducerService")
public class MQProducerServiceImpl implements MQProducerService{
    @Autowired
    JmsTemplate jmsTemplate;

    Logger logger = Logger.getLogger(MQProducerServiceImpl.class);

    @Override
    public void sendSeckillMessage(Destination destination, SeckillAction sa) {
        logger.info("向队列" + destination.toString() + "发送对象" + sa.getClass());
        jmsTemplate.send(destination, new MessageCreator() {

            @Override
            public Message createMessage(Session session) throws JMSException {
                ObjectMessage om = session.createObjectMessage(sa);
                return om;
            }
        });
    }

    @Override
    public void sendSeckillMessage(SeckillAction sa) {
        Destination dest = jmsTemplate.getDefaultDestination();
        sendSeckillMessage(dest, sa);
    }


}

Listener实现

package com.shu.yzy.activemq;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.shu.yzy.dto.SeckillAction;
import com.shu.yzy.service.SeckillService;

/** 从消息队列监听器
 * @author Administrator
 *
 */
public class SeckillMessageListener implements MessageListener{
    private static Logger logger = Logger.getLogger(SeckillMessageListener.class);

    @Override
    public void onMessage(Message msg) {
        if(msg instanceof ObjectMessage) {
            ObjectMessage tm = (ObjectMessage) msg;
            try {
                logger.info("从消息队列中消费一个对象!!");
                SeckillAction sa = (SeckillAction)tm.getObject();
                logger.info(sa.toString());
                //具体的业务逻辑
                //seckillService.consumeSeckillAction(sa);

            } catch (JMSException e) {
                e.printStackTrace();
            }
        } else if(msg instanceof TextMessage) {
            //do sth....
        }
    }


}

单元测试类

package com.shu.yzy.test;

import java.util.Date;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;

import com.shu.yzy.activemq.service.MQProducerService;
import com.shu.yzy.dto.SeckillAction;

/*单元测试类*/
@RunWith(org.springframework.test.context.junit4.SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class UnitTest {

    @Resource
    MQProducerService mqProducerService;

    @Test
    public void testRole() {
        Long sid = new Long(1000);
        Integer uid = 1;
        SeckillAction sa = new SeckillAction(sid, uid, new Date());
        mqProducerService.sendSeckillMessage(sa);
    }

}

运行结果

2018-09-06 20:14:43,667 [main] INFO  [com.shu.yzy.activemq.service.impl.MQProducerServiceImpl] - 向队列queue://seckill发送对象class com.shu.yzy.dto.SeckillAction
2018-09-06 20:14:43,750 [queueListenerContainer-1] INFO  [com.shu.yzy.activemq.SeckillMessageListener] - 从消息队列中消费一个对象!!
2018-09-06 20:14:43,753 [queueListenerContainer-1] INFO  [com.shu.yzy.activemq.SeckillMessageListener] - SeckillAction [seckill_id=1000, id=1, now=Thu Sep 06 20:14:43 CST 2018]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值