zoukankan      html  css  js  c++  java
  • 如何用Spring整和ActiveMQ?

    问题一:为什么要整合ActiveMQ?

      传统的JDBC代码在处理连接、语句、结果集和异常时是多么冗长和繁杂你一定不会忘记,传统的JMS继承了JDBC的“关荣传统”。发送一个简单的消息,要几行代码呢?请仔细数数吧。

      Java代码

    以下是引用片段:
    public void sendMessage() throws JMSException {    
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(    
        "tcp://localhost:61616");    
        Connection connection = null;    
        Session session=null;    
        try {    
                
            connection = (Connection) connectionFactory.createConnection();//创建连接    
            session = (Session) connection.createSession(false,    
                    Session.AUTO_ACKNOWLEDGE);//创建会话    
            Destination destination = session.createQueue("myQueue");    
            MessageProducer producer = session.createProducer(destination);    
            TextMessage message = session.createTextMessage(expectedBody);    
            message.setStringProperty("headname", "remoteB");    
            producer.send(message);    
            connection.close();    
        } catch (Exception e) {    
            e.printStackTrace();    
        }finally{    
            try {    
                if(session!=null){    
                    session.close();    
                }    
                if(connection!=null){    
                    connection=null;    
                }    
            } catch (Exception e) {    
                    
            }    
        }    
    }   
     public void sendMessage() throws JMSException { 
      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory( 
      "tcp://localhost:61616"); 
      Connection connection = null; 
      Session session=null; 
      try { 
        
       connection = (Connection) connectionFactory.createConnection();//创建连接 
       session = (Session) connection.createSession(false, 
         Session.AUTO_ACKNOWLEDGE);//创建会话 
       Destination destination = session.createQueue("myQueue"); 
       MessageProducer producer = session.createProducer(destination); 
       TextMessage message = session.createTextMessage(expectedBody); 
       message.setStringProperty("headname", "remoteB"); 
       producer.send(message); 
       connection.close(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      }finally{ 
       try { 
        if(session!=null){ 
         session.close(); 
        } 
        if(connection!=null){ 
         connection=null; 
        } 
       } catch (Exception e) { 
         
       } 
      } 
     } 

      传统接受消息而是类似的代码,其实我们的目的就是发送和接受消息。幸运的是Spring为我们提供了大量的模板。项目一期用的较多的是JdbCTemplate,spring也为我们提供了JMSTemplate模板。

      问题二:JMSTemplate模板该如何配置呢?

      类似于jdbcTemplate,首先要配置一个ConnectionFactory,我们采用ActiveMQ5.2作为消息服务器。之后要开始配置JmsTemplate模板了。最后是配置消息目标了。消息分为队列和主题两大类,因此要配置两个消息目标了。

      Java代码

    以下是引用片段:
    <!-- ActiveMQ -->    
            
        <!-- 配置JMS连接工厂 -->      
        <bean id="JmsConnectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">      
            <property name="brokerURL" value="tcp://localhost:61616"/>      
        </bean>      
        <!-- 配置JMS模版 -->      
        <bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">      
            <property name="connectionFactory" ref="JmsConnectionFactory"/>      
        </bean>      
        <!-- 发送消息的目的地(队列) -->      
        <bean id="QueueDestination" class="org.apache.activemq.command.ActiveMQQueue">      
            <!-- 设置消息队列的名字 -->      
            <constructor-arg index="0" value="HelloWorldQueue"/>      
        </bean>    
        <!-- 发送消息的目的地(主题) -->      
        <bean id="TopicDestination" class="org.apache.activemq.command.ActiveMQTopic">      
            <!-- 设置消息主题的名字 -->      
            <constructor-arg index="0" value="FlexTopic"/>      
        </bean>      
    <!-- ActiveMQ --> 
         
        <!-- 配置JMS连接工厂 -->   
        <bean id="JmsConnectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">   
         <property name="brokerURL" value="tcp://localhost:61616"/>   
        </bean>   
        <!-- 配置JMS模版 -->   
        <bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">   
         <property name="connectionFactory" ref="JmsConnectionFactory"/>   
        </bean>   
        <!-- 发送消息的目的地(队列) -->   
        <bean id="QueueDestination" class="org.apache.activemq.command.ActiveMQQueue">   
         <!-- 设置消息队列的名字 -->   
         <constructor-arg index="0" value="HelloWorldQueue"/>   
        </bean> 
        <!-- 发送消息的目的地(主题) -->   
        <bean id="TopicDestination" class="org.apache.activemq.command.ActiveMQTopic">   
         <!-- 设置消息主题的名字 -->   
         <constructor-arg index="0" value="FlexTopic"/>   
        </bean>    

      问题三:如何使用JmsTemplate发送消息呢?

      spring的beanfactory得到一个jmsTemplate的实例和消息目标的实例,发送消息,够简单的吧。看看代码:

      Java代码

    以下是引用片段:
    JmsTemplate template = (JmsTemplate) SpringContext.getBean("JmsTemplate");    
                ActiveMQTopic destination=(ActiveMQTopic)SpringContext.getBean("TopicDestination");    
                template.send((javax.jms.Destination) destination, new MessageCreator(){    
                    public Message createMessage(Session session) throws JMSException {    
                        return session.createTextMessage("hello");    
                    }    
                        
                });   
    JmsTemplate template = (JmsTemplate) SpringContext.getBean("JmsTemplate"); 
       ActiveMQTopic destination=(ActiveMQTopic)SpringContext.getBean("TopicDestination"); 
       template.send((javax.jms.Destination) destination, new MessageCreator(){ 
        public Message createMessage(Session session) throws JMSException { 
         return session.createTextMessage("hello"); 
        } 
         
       }); 

      问题四:上面的代码能不能在简单些?

      很多时候,发送消息的目标都是默认的,因此是不是可以在jmsTemplate中设置一个默认的消息目标呢?答案是肯定的。

      Java代码

    以下是引用片段:
    <!-- 配置JMS模版 -->      
       <bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">      
        <property name="connectionFactory" ref="JmsConnectionFactory"/>    
        <property name="defaultDestination" ref="TopicDestination"></property>    
       </bean>    
     <!-- 配置JMS模版 -->   
        <bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">   
         <property name="connectionFactory" ref="JmsConnectionFactory"/> 
         <property name="defaultDestination" ref="TopicDestination"></property> 
        </bean>  

      发送消息的时候,不指定目标,spring就会调用默认的目标了。

      Java代码

    以下是引用片段:
    JmsTemplate template = (JmsTemplate) SpringContext.getBean("JmsTemplate");    
                template.send( new MessageCreator(){    
                    public Message createMessage(Session session) throws JMSException {    
                        return session.createTextMessage("hello");    
                    }    
                });   
    JmsTemplate template = (JmsTemplate) SpringContext.getBean("JmsTemplate"); 
       template.send( new MessageCreator(){ 
        public Message createMessage(Session session) throws JMSException { 
         return session.createTextMessage("hello"); 
        } 
       }); 

      问题四:jmsTemplate怎么接受信息?

      jmsTemplate接收消息十分的简单,只需要调用template.receive()方法,receive方法是同步的,默认情况下,对receive()方法的调用会造成阻塞,知道消息到达目标----如果必要,永远等下去。为了避免对消息内容等待,可以配置jmsTemplate时,通过设置receiveTimeout属性来指定接收消息超时时间。下面的配置将接收消息的超时时间设置为一分钟(60000毫秒)。

      Xml代码

    以下是引用片段:
    <!-- 配置JMS模版 -->      
       <bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">      
        <property name="connectionFactory" ref="JmsConnectionFactory"/>   
        <property name="defaultDestination" ref="TopicDestination"></property>   
        <property name="receiveTimeout" value="60000"></property>   
       </bean>     
     <!-- 配置JMS模版 -->   
        <bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">   
         <property name="connectionFactory" ref="JmsConnectionFactory"/> 
         <property name="defaultDestination" ref="TopicDestination"></property> 
         <property name="receiveTimeout" value="60000"></property> 
        </bean>  
     

      template.receive()会从默认目标接收消息,如果你希望指定一个目标,可以传一个目标。如:template.receive("myQueue").

      同步接收消息并不是spring唯一的选择,消息监听器可以实现异步(下篇文章将会介绍消息驱动)。

      问题五:怎么自动将消息转化为Java对象?

      转化器在很多组件中都是必不缺少的东西。Spring挺过MessageConverter接口提供了对消息转换的支持。

      Java代码

    以下是引用片段:
    public class MyMessageConverter implements MessageConverter {    
        @Override   
        public Object fromMessage(Message arg0) throws JMSException,    
                MessageConversionException {    
            // TODO Auto-generated method stub    
            return null;    
        }    
        @Override   
        public Message toMessage(Object arg0, Session arg1) throws JMSException,    
                MessageConversionException {    
            // TODO Auto-generated method stub    
            return null;    
        }    
    }   
    public class MyMessageConverter implements MessageConverter { 
     @Override 
     public Object fromMessage(Message arg0) throws JMSException, 
       MessageConversionException { 
      // TODO Auto-generated method stub 
      return null; 
     } 
     @Override 
     public Message toMessage(Object arg0, Session arg1) throws JMSException, 
       MessageConversionException { 
      // TODO Auto-generated method stub 
      return null; 
     } 
    }

      MessageConverter接口的两个方法简单明了。在发送端toMessage会将java对象转化为消息,在接收端fromMessage会将消息转化为java对象。

      下面的代码简单的实现了MessageConverter的两个接口。

    以下是引用片段:
      Java代码  
    public class MyMessageConverter implements MessageConverter {    
        @Override   
        public Object fromMessage(Message message) throws JMSException,    
                MessageConversionException {    
            if(!(message instanceof MapMessage)){    
                throw new MessageConversionException("Messae is not MapMessage");    
            }    
            MapMessage mapMessage=(MapMessage)message;    
            MessageObj messageObj=new MessageObj();    
            messageObj.setId(mapMessage.getString("id"));    
            messageObj.setInfo(mapMessage.getString("info"));    
            return messageObj;    
        }    
        @Override   
        public Message toMessage(Object obj, Session session) throws JMSException,    
                MessageConversionException {    
            if(!(obj instanceof MessageObj)){    
                throw new MessageConversionException("obj is not MessageObj");    
            }    
            MessageObj messageObj=(MessageObj)obj;    
            MapMessage mapMessage=session.createMapMessage();    
            mapMessage.setString("id", messageObj.getId());    
            mapMessage.setString("info", messageObj.getInfo());    
            return mapMessage;    
        }    
    }   
    public class MyMessageConverter implements MessageConverter { 
     @Override 
     public Object fromMessage(Message message) throws JMSException, 
       MessageConversionException { 
      if(!(message instanceof MapMessage)){ 
       throw new MessageConversionException("Messae is not MapMessage"); 
      } 
      MapMessage mapMessage=(MapMessage)message; 
      MessageObj messageObj=new MessageObj(); 
      messageObj.setId(mapMessage.getString("id")); 
      messageObj.setInfo(mapMessage.getString("info")); 
      return messageObj; 
     } 
     @Override 
     public Message toMessage(Object obj, Session session) throws JMSException, 
       MessageConversionException { 
      if(!(obj instanceof MessageObj)){ 
       throw new MessageConversionException("obj is not MessageObj"); 
      } 
      MessageObj messageObj=(MessageObj)obj; 
      MapMessage mapMessage=session.createMapMessage(); 
      mapMessage.setString("id", messageObj.getId()); 
      mapMessage.setString("info", messageObj.getInfo()); 
      return mapMessage; 
     } 

      此时,发送和接收消息要换成template.convertAndSend(message);template.receiveAndConvert();

      可是jmsTemplate如何知道消息转换器呢?需要在配置jmsTemplate的时候,加上messageConverter属性。

      Java代码

    以下是引用片段:
    <!-- 配置JMS模版 -->      
       <bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">      
        <property name="connectionFactory" ref="JmsConnectionFactory"/>    
        <property name="defaultDestination" ref="TopicDestination"></property>    
        <property name="receiveTimeout" value="60000"></property>    
        <property name="messageConverter" ref="messageObj"></property>    
       </bean>     
     <!-- 配置JMS模版 -->   
        <bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">   
         <property name="connectionFactory" ref="JmsConnectionFactory"/> 
         <property name="defaultDestination" ref="TopicDestination"></property> 
         <property name="receiveTimeout" value="60000"></property> 
         <property name="messageConverter" ref="messageObj"></property> 
        </bean>   

      messageObj是要转化的java对象的bean的id。

  • 相关阅读:
    Apache Hadoop 英文官方参考文档及中文文档
    谷歌大数据那三篇论文-中文版
    Java学习笔记(一):基础概念和语法
    Java基础概念、知识点整理
    TensorFlow基础知识
    Kafka集群环境配置
    Sqoop数据迁移工具的使用
    HBase的安装和使用
    Flume日志采集框架的使用
    zookeeper的安装和使用
  • 原文地址:https://www.cnblogs.com/java20130722/p/3207006.html
Copyright © 2011-2022 走看看