zoukankan      html  css  js  c++  java
  • Spring整合JMS(一)-基础篇

     1.基础知识

       

                图1   同步通信和异步通信通信过程示意图

      RMI使用的是同步通信,JMS使用的是异步通信。从图1可以看出异步通信的好处就是减少了不必要的等待,提高了效率。

      JMS中有两个主要的概念:消息代理(message broker)和目的地(destination)。

      消息代理指的概念:    发送者将消息发送到消息代理服务器,代理服务器收到消息后提示接收端去接收消息,消息代理就起了控制消息流转的作用,Apache 的activemq就是一种消息代理服务器。

      目的地指的概念:   消息发送的目标地址,也是消息接收者获取消息的目标地址,对应于queue和topic中的一种,并且要指定具体的名称。

      

      JMS通信又分为点对点和点对多2种形式。

      点对点通信形式如图12.3所示,采用javax.jms.Queue表示,点多多通信形式如图12.4所示,采用javax.jms.Topic表示

      

      

      同步通信的缺点,这也是使用JMS所能够解决的:

          

      2.Spring对JMS的支持

      为了消除重复冗余的JMS代码,如建立连接,异常处理等,我们应该使用Spring所提供的JmsTemplate来进行消息的发送与接收。

      和JDBCTemplate类似,JmsTemplate将捕获JMS所抛出的检查时异常,进行封装并以非检查时异常的形式进行抛出,我们就不必须对异常进行捕获。

      

      3.示例代码

       JMS只是一种标准,Apache的activemq是其多种实现中的一种,下面将基于activemq来做示例。

       示例代码将分为发送端代码,接收端代码,XML配置和测试类4部分。

       首先要下载apache-activemq,运行apache-activemq-5.10.0-bin[1]apache-activemq-5.10.0inwin32下面的activemq.bat启动JMS服务,确保已经正常启动,61616端口未被占用。

       3.1 发送端代码

       发送消息的代码,注意要使用JmsTemplate:  

    @Component("producerServiceImpl")
    public class ProducerServiceImpl implements ProducerService {
                private JmsTemplate jmsTemplate;
    public void sendMessage(Destination destination, final String message) {
                  jmsTemplate.send(destination, new MessageCreator() {
    public Message createMessage(Session session) throws JMSException {
                        return session.createTextMessage(message);
                    }
                });
            } 
    
                public JmsTemplate getJmsTemplate() {
                    return jmsTemplate;
                } 
    
                @Resource
                public void setJmsTemplate(JmsTemplate jmsTemplate) {
                    this.jmsTemplate = jmsTemplate;
                }
    }

       

     3.2 接收端代码 

      

      使用EJB的消息驱动来处理消息的代码如下,这样onMessage方法不会阻塞,但是要绑定MessageListener接口:

        

      使用Spring所支持JMS接收消息的配置如下,比使用JmsTemplate和集成MessageListener接口要好:

      

      需要在配置文件中做如下的配置:

     

        配置一个listener-container,将消息接收端的bean放在其中

     

       3.3.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"
        xmlns:jms="http://www.springframework.org/schema/jms"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">
     
        <context:component-scan base-package="com.tiantian" />
     
        <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
            <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
            <property name="connectionFactory" ref="connectionFactory"/>
        </bean>
        
        <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
        <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL" value="tcp://localhost:61616"/>
        </bean>
        
        <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
        <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
            <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
            <property name="targetConnectionFactory" ref="targetConnectionFactory"/>
        </bean>
        
        <!--这个是队列目的地-->
        <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg>
                <value>queue</value>
            </constructor-arg>
        </bean>
        <!-- 消息监听器 -->
        <bean id="consumerMessageListener" class="com.tiantian.springintejms.listener.ConsumerMessageListener"/>
        <!-- 消息监听容器 -->
        <bean id="jmsContainer"
            class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="connectionFactory" />
            <property name="destination" ref="queueDestination" />
            <property name="messageListener" ref="consumerMessageListener" />
        </bean>
    </beans>

       3.4.测试类代码

      测试的代码如下所示:

    import javax.jms.Destination;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import com.tiantian.springintejms.service.ProducerService;
     
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("/applicationContext.xml")
    public class ProducerConsumerTest {
     
        @Autowired
        private ProducerService producerService;
        @Autowired
        @Qualifier("queueDestination")
        private Destination destination;
        
        @Test
        public void testSend() {
            for (int i=0; i<2; i++) {
                producerService.sendMessage(destination, "你好,生产者!这是消息:" + (i+1));
            }
        }
        
    }

     

  • 相关阅读:
    设计模式二(建造者、原型、桥接)
    MSSQL根据表名动态分页的存储过程以及C#.net调用使用
    查询身份证号码信息(C#.NET)
    初试三层+抽象工厂代码生成器
    NET多线程与异步编程
    【SQL.SERVER.DMVS.实战】学习笔记
    【SQL.SERVER.DMVS.实战】学习笔记(二)
    SQL Server 2005数据文件数据的存储
    ASP.NET第九天加强课程
    ASP.NET第四天加强课程
  • 原文地址:https://www.cnblogs.com/lnlvinso/p/4126340.html
Copyright © 2011-2022 走看看