如何用Spring整和ActiveMQ?

日期: 2010-12-20 作者:yunzhongxia 来源:TechTarget中国 英文

  问题一:为什么要整合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。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐