MQ 入门(二)——activeMQ 与spring 整合

1、通过上一节【】,我们对消息队列和jms 有了一定的了解,但是像第一节中编写异步消息通讯比较麻烦,通过与spring的整合,我们使用起来会非常简单。

本例子采用maven构建,具体代码如下所示:

pom文件如下:主要使用的jar包有spring相关的,junit相关,mq相关

<!-- Spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
        <scope>provided</scope>
    </dependency>
    <!-- activemq -->
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-spring</artifactId>
        <version>${activemq.version}</version>
    </dependency>
    <!-- spring-jms -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- 日志 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <!-- 单元测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>

activemq 相关配置文件如下:
applicationContext-activemq.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:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:amq="http://activemq.apache.org/schema/core"
    xmlns:jms="http://www.springframework.org/schema/jms"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd 
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-4.0.xsd
    http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.8.0.xsd"
    default-lazy-init="false">

    <!-- ActiveMQ 连接工厂 -->
    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
    <!-- 如果连接网络:tcp://ip:61616;未连接网络:tcp://localhost:61616 以及用户名,密码-->
    <amq:connectionFactory id="amqConnectionFactory" brokerURL="${activemq.url}" 
     trustAllPackages="true" userName="${activemq.username}" password="${activemq.password}" />

    <!-- Spring Caching连接工厂 -->
    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
    <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
        <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
        <property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
        <!-- Session缓存数量 -->
        <property name="sessionCacheSize" value="${activemq.sessioncachesize}"></property>
    </bean>

    <!-- Spring JmsTemplate 的消息生产者 start-->
    <!-- 定义JmsTemplate的Queue类型 -->
    <bean id="queueTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->  
        <constructor-arg ref="connectionFactory" />
        <!-- 非pub/sub模型(发布/订阅),即队列模式 -->
        <property name="pubSubDomain" value="false" />
    </bean>
    <!--Spring JmsTemplate 的消息生产者 end-->

</beans>

生产者如下:

/**
 * mq 生产者
 * @author Administrator
 *
 */
@Service
public class StudentProducerService {

    public final static Logger logger = LoggerFactory.getLogger(StudentProducerService.class);

    /**
     * 队列名称
     */
    @Value("${test.queue}")
    private String queueName;

    @Autowired
    private JmsTemplate queueTemplate;

    /**
     * 将消息发送至mq的队列中
     */
    public void sendMessage(final Student student){
        queueTemplate.send(queueName, new MessageCreator() {

            @Override
            public Message createMessage(Session session) throws JMSException {
                ObjectMessage message = session.createObjectMessage();
                logger.debug("生产者将发送消息:【producer】"+student.toString());
                message.setObject(student);
                return message;
            }
        });
    }
}

消费者:

/**
 * mq 消费者
 * @author Administrator
 *
 */
@Service
public class StudentConsumerService {

    public final static Logger logger = LoggerFactory.getLogger(StudentConsumerService.class);

    /**
     * 队列名称
     */
    @Value("${test.queue}")
    private String queueName;

    @Autowired
    private JmsTemplate queueTemplate;

    /**
     * 接收消息
     */
    public void receiverMessage(){

        Message message = (Message) queueTemplate.receive(queueName);
        ObjectMessage objMessage = (ObjectMessage) message;
        try {
            Object obj = objMessage.getObject();
            if(obj instanceof Student){

                logger.debug("服务器收到消息:+【receiver】"+obj.toString());
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }

    }
}

测试运行代码如下:

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration({"classpath:spring/applicationContext*.xml"}) 
public class StudentProducerServiceTest {

    @Autowired
    private StudentProducerService studentProducerService;

    @Autowired
    private StudentConsumerService studentConsumerService;

    @Test
    public void testSendMessage() {
        final Student student = new Student("201712291122", "onionflower", 12, 2);
        System.out.println("准备开始运行生产者。。。。");
        studentProducerService.sendMessage(student);
        System.out.println("准备开始运行消费者。。。。");
        studentConsumerService.receiverMessage();
    }

}

运行结果:
这里写图片描述
从上面的测试结果我们可以看到,生产者生产一条消息,消费者消费一条消息,但我们会发现该用例存在问题:
1、消费者需要手动运行,做不到随时监听队列【如果发现有消息,自动进行消费】。
2、代码不够优化。

优化后代码如下:
配置文件增加:
applicationContext-activemq.xml

    <bean id="queueReceiver"  class="com.onion.mq.optimize.OptimizeConsumerService"></bean>
    <!-- 定义Queue监听器 -->
    <jms:listener-container destination-type="queue" container-type="default" receive-timeout="5000" connection-factory="connectionFactory" acknowledge="auto">
        <jms:listener destination="${test.queue}" ref="queueReceiver"/>
    </jms:listener-container>

生产者:

/**
 * 优化之后的生产者
 * @author Administrator
 *
 */
@Service
public class OptimizeProducerService{

    public final static Logger logger = LoggerFactory.getLogger(OptimizeProducerService.class);



    /**
     * 队列名称
     */
    @Value("${test.queue}")
    private String queueName;

    /**
     * 对jmstemplete 的包装,将发送消息的方法统一包装
     */
    @Autowired
    private MqService mqService;


    /**
     * 将消息发送至mq的队列中
     */
    public void sendMessage( Student student){
        logger.debug("生产者将发送消息:【producer】"+student.toString());
        StudentMessageCreator studentCreator = new StudentMessageCreator(student);
        mqService.queueSend(queueName, studentCreator);
    }
}

封装jmsTemplete

/**
 * @author onionflower
 * @date 2017年7月12日
 */
@Service
public class MqService {

    @Autowired(required=false)
    private JmsTemplate queueTemplate;

    public void queueSend(String queueName,MessageCreator messageCreator){
        queueTemplate.send(queueName,messageCreator);
    }
}

将messageCreator提取出来

/**
 * 优化产生的代码,我们将生产者中的new MessageCreator提取出来,单独生成一个类
 * @author Administrator
 *
 */
public class StudentMessageCreator implements MessageCreator{

    private Student student;


    public StudentMessageCreator(Student student) {
        super();
        this.student = student;
    }



    @Override
    public Message createMessage(Session session) throws JMSException {
        ObjectMessage message = session.createObjectMessage();
        message.setObject(student);
        return message;
    }

}

消费者:

/**
 * mq 消费者
 * @author Administrator
 *
 */
public class OptimizeConsumerService  implements MessageListener{


    public final static Logger logger = LoggerFactory.getLogger(OptimizeConsumerService.class);

    @Override
    public void onMessage(Message message) {
        ObjectMessage objMessage = (ObjectMessage) message;
        Object obj = null;
        try {
            obj = objMessage.getObject();
            if(obj instanceof Student){

                logger.debug("服务器收到消息:+【receiver】"+obj.toString());
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }

    }
}

运行结果如下:
这里写图片描述
我们只需要运行生产者,消费者会自动监听队列中是否有未消费的消息,如果有,直接拿过去消费。
这里写图片描述

二、ActiveMQ集群配置
activemq集群,我们只需要修改spring的配置文件:将连接工厂的相关配置修改即可。具体代码如下:

<amq:connectionFactory id="amqConnectionFactory" brokerURL="${activemq.url}" 
     trustAllPackages="true" userName="${activemq.username}" password="${activemq.password}" />

关于properties配置文件如下:
activemq.url=failover:(tcp://xxxx:61616,tcp://xxxxx:61616,tcp://xxxxx:61616)?initialReconnectDelay=0&maxReconnectAttempts=3&timeout=2000
activemq.username=admin
activemq.password=admin
activemq.sessioncachesize=100

源码下载地址如下:http://download.csdn.net/download/u012151597/10179978

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值