Spring整合JMS

项目最终目录结构如下:
这里写图片描述

项目源码:http://download.csdn.net/detail/u011983531/9239911

1、在src目录下建立spring-jms.xml文件

下面对文件中各个部分的配置进行详解

(1)配置ConnectionFactory

Spring为我们提供了SingleConnectionFactory和CachingConnectionFactory。SingleConnectionFactory对于建立JMS服务器链接的请求会一直返回同一个链接,并且会忽略Connection的close方法调用。CachingConnectionFactory继承了SingleConnectionFactory,所以它拥有SingleConnectionFactory的所有功能,同时它还新增了缓存功能,它可以缓存Session、MessageProducer和MessageConsumer。但是Spring提供的ConnectionFactory只是Spring用于管理ConnectionFactory的,真正创建JMS服务器链接的ConnectionFactory还得由JMS服务厂商(这里我们选择ActiveMQ)提供,并且需要把它注入到Spring提供的ConnectionFactory中。

<!-- 真正的可产生连接的连接工厂 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="tcp://localhost:61616"></property>
</bean>

<!-- Spring用于管理ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory" ref="targetConnectionFactory"></property>
</bean>

(2)配置生产者

生产者负责发送消息到JMS服务器,这通常对应一个业务逻辑类。在业务逻辑类中利用Spring为我们提供的JmsTemplate类发送消息,所以配置生产者主要就是配置JmsTemplate。对于生产者而言,在发送消息的时候要知道往哪里发,为此,在配置JmsTemplate的时候需要往里面注入一个Spring提供的ConnectionFactory对象。
在真正利用JmsTemplate进行消息发送的时候,我们需要知道消息发送的目的地,即destination。在ActiveMQ中实现了两种类型的Destination,一个是点对点的ActiveMQQueue,另一个就是订阅/发布模式的ActiveMQTopic。
业务逻辑类代码如下:

package com.ghs.jms.service;

import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.jms.JmsException;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;

@Component("messageService")
public class MessageService {

    @Resource(name="jmsTemplate")
    private JmsTemplate jmsTemplate;

    public void sendMessage(Destination destination,final String msg){
        try {
            jmsTemplate.send(destination,new MessageCreator() {
                @Override
                public Message createMessage(Session session) throws JMSException {
                    return session.createTextMessage(msg);
                }
            });
        } catch (JmsException e) {
            e.printStackTrace();
        }
    }
}
<!-- Spring提供的JMS工具类,可以用来接收、发送消息 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="connectionFactory"></property>
</bean>

<!-- 目的地队列 -->
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg>
        <value>FirstQueue</value>
    </constructor-arg>
</bean>

(3)配置消费者

生产者往指定目的地Destination发送消息后,接下来就是消费者对指定目的地的消息进行消费了。那么消费者是如何知道有生产者发送消息到指定目的地Destination了呢?这是通过Spring为我们封装的消息监听容器MessageListenerContainer实现的,它负责接收信息,并把接收到的信息分发给真正的MessageListener进行处理。每个消费者对应每个目的地都需要有对应的MessageListenerContainer。对于消息监听容器而言,除了要知道监听哪个目的地之外,还需要知道到哪里去监听,也就是说它还需要知道去监听哪个JMS服务器,这是通过在配置MessageConnectionFactory的时候往里面注入一个ConnectionFactory来实现的。所以我们在配置一个MessageListenerContainer的时候有三个属性必须指定,一个是表示从哪里监听的ConnectionFactory;一个是表示监听什么的Destination;一个是接收到消息以后进行消息处理的MessageListener。

Spring一共为我们提供了两种类型的MessageListenerContainer:SimpleMessageListenerContainer和DefaultMessageListenerContainer。
SimpleMessageListenerContainer会在一开始的时候就创建一个会话session和消费者Consumer,并且会使用标准的JMS MessageConsumer.setMessageListener()方法注册监听器让JMS提供者调用监听器的回调函数。它不会动态的适应运行时需要和参与外部的事务管理。兼容性方面,它非常接近于独立的JMS规范,但一般不兼容Java EE的JMS限制。
大多数情况下我们还是使用的DefaultMessageListenerContainer,跟SimpleMessageListenerContainer相比,DefaultMessageListenerContainer会动态的适应运行时需要,并且能够参与外部的事务管理。它很好的平衡了对JMS提供者要求低、先进功能如事务参与和兼容Java EE环境。

定义处理消息的MessageListener,如下:

package com.ghs.jms.listener;

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

public class ConsumerMessageListener implements MessageListener {

    @Override
    public void onMessage(Message message) {
        TextMessage msg = (TextMessage) message;
        try {
            System.out.println("收到:"+msg.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}
<!-- 目的地队列 -->
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg>
        <value>FirstQueue</value>
    </constructor-arg>
</bean>

<!-- 消息监听器 -->
<bean id="messageListener" class="com.ghs.jms.listener.ConsumerMessageListener">
</bean>

<!-- 消息监听容器 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory"></property>
    <property name="destination" ref="destination"></property>
    <property name="messageListener" ref="messageListener"></property>
</bean>

2、单元测试

定义测试类:

package com.ghs.jms.test;

import javax.annotation.Resource;
import javax.jms.Destination;

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

import com.ghs.jms.service.MessageService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-jms.xml")
public class MessageServiceTest {

    @Resource(name="destination")
    private Destination destination;

    @Resource(name="messageService")
    private MessageService messageService;

    @Test
    public void testSend(){
        for(int i=0; i<10; i++){
            String text = "第"+i+"条消息";
            System.out.println("发送:"+text);
            messageService.sendMessage(destination, text);
        }
    }
}

测试结果:
发送:第0条消息
收到:第0条消息
发送:第1条消息
收到:第1条消息
发送:第2条消息
收到:第2条消息
发送:第3条消息
收到:第3条消息
发送:第4条消息
收到:第4条消息
发送:第5条消息
收到:第5条消息
发送:第6条消息
收到:第6条消息
发送:第7条消息
收到:第7条消息
发送:第8条消息
收到:第8条消息
发送:第9条消息
收到:第9条消息

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值