用Spring发送和接受JMS消息的一个小例子

jopen 5年前

摘要 和通过直接使用JMS的API相比,大大简化了代码的编写。

Spring提供的JmsTemplate对原生的JMS API进行了一层薄薄的封装,使用起来非常的方便。

我使用的JMS消息代理插件是Apache的ActiveMQ,建议安装最新版本,因为我之前安装老版本,各种不兼容,各种bug,最新版的activemq-all-5.9.1.jar包里面已经有了slf4j.impl包,之前就是被这个坑了...把这个jar包加到lib目录下面,就不会有各种ClassNotFound异常和类冲突的bug了。

下载ActiveMQ解压之后运行bin下面的activemq.bat就可以运行了。你可以访问http://127.0.0.1:8161/看看服务是否正常开启

默认账户密码是admin/admin

下面这个例子是一个邮局系统,包括前后台两个子系统,当前台收到一封邮件的时候,它将这封邮件传递给后台,同时发送一个JMS消息给后台子系统,提醒新的邮件。

JMS有两种消息通信模型:

    1)、point-to-point 

    2)、pub/sub

这里我们当然是用的第一种模型.

首先我们建立一个Mail类:

package com.apress.springrecipes.post;    public class Mail {   private String mailId;   private String country;   private double weight;     public Mail() {   }     public Mail(String mailId, String country, double weight) {    this.mailId = mailId;    this.country = country;    this.weight = weight;   }     public String getMailId() {    return mailId;   }     public void setMailId(String mailId) {    this.mailId = mailId;   }     public String getCountry() {    return country;   }     public void setCountry(String country) {    this.country = country;   }     public double getWeight() {    return weight;   }     public void setWeight(double weight) {    this.weight = weight;   }  }

一个前台子系统接口:

package com.apress.springrecipes.post;    public interface FrontDesk {   public void sendMail(Mail mail);  }

和它的实现类:

package com.apress.springrecipes.post;    import javax.jms.Destination;  import javax.jms.JMSException;  import javax.jms.MapMessage;  import javax.jms.Message;  import javax.jms.Session;    import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.jms.core.JmsTemplate;  import org.springframework.jms.core.MessageCreator;    public class FrontDeskImpl2 implements FrontDesk {   @Autowired   private JmsTemplate jmsTemplate;   @Autowired   private Destination destination;   @Override   public void sendMail(final Mail mail) {    jmsTemplate.send(destination,new MessageCreator() {          @Override     public Message createMessage(Session session) throws JMSException {      MapMessage message = session.createMapMessage();      message.setString("mailId", mail.getMailId());      message.setString("country", mail.getCountry());      message.setDouble("weight", mail.getWeight());      return message;     }    });   }  }

一个后台子系统的接口:

package com.apress.springrecipes.post;    public interface BackOffice {   public Mail receiveMail();  }

和它的实现类:

package com.apress.springrecipes.post;    import javax.jms.Destination;  import javax.jms.JMSException;  import javax.jms.MapMessage;    import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.jms.core.JmsTemplate;  import org.springframework.jms.support.JmsUtils;    public class BackOfficeImpl2 implements BackOffice {   @Autowired   private JmsTemplate jmsTemplate;   @Autowired   private Destination destination;     @Override   public Mail receiveMail() {    MapMessage message = (MapMessage) jmsTemplate.receive(destination);    try {     if (message == null) {      return null;     }     Mail mail = new Mail();     mail.setMailId(message.getString("mailId"));     mail.setCountry(message.getString("country"));     mail.setWeight(message.getDouble("weight"));     return mail;    } catch (JMSException e) {     throw JmsUtils.convertJmsAccessException(e);    }   }  }

前台子系统的xml配置文件bean-front.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"   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">     <context:annotation-config/>      <bean id="frontDesk"     class="com.apress.springrecipes.post.FrontDeskImpl2" />     <bean id="connectionFactory"    class="org.apache.activemq.ActiveMQConnectionFactory">    <property name="brokerURL" value="tcp://localhost:61616"/>   </bean>     <bean id="destination"    class="org.apache.activemq.command.ActiveMQQueue">    <constructor-arg value="mail.queue" />   </bean>     <bean id="jmsTemplate"    class="org.springframework.jms.core.JmsTemplate">    <property name="connectionFactory" ref="connectionFactory"/>   </bean>     </beans>

后台子系统的xml配置文件bean-back.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"   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">      <context:annotation-config />      <bean id="backOffice"    class="com.apress.springrecipes.post.BackOfficeImpl2" />     <bean id="connectionFactory"    class="org.apache.activemq.ActiveMQConnectionFactory">    <property name="brokerURL" value="tcp://localhost:61616" />   </bean>     <bean id="destination"    class="org.apache.activemq.command.ActiveMQQueue">    <constructor-arg value="mail.queue" />   </bean>     <bean id="jmsTemplate"    class="org.springframework.jms.core.JmsTemplate">    <property name="connectionFactory" ref="connectionFactory" />    <property name="receiveTimeout" value="10000" />   </bean>    </beans>

两个测试类,一个是发消息,一个是接受消息。

package com.apress.springrecipes.post;    import org.springframework.context.ApplicationContext;  import org.springframework.context.support.ClassPathXmlApplicationContext;    public class FrontDeskMain {   public static void main(String[] args) {    ApplicationContext context = new ClassPathXmlApplicationContext("beans-front.xml");    FrontDesk frontDesk = (FrontDesk) context.getBean("frontDesk");    frontDesk.sendMail(new Mail("1234","US",1.5));   }  }

package com.apress.springrecipes.post;    import org.springframework.context.ApplicationContext;  import org.springframework.context.support.ClassPathXmlApplicationContext;    public class BackOfficeMain {   public static void main(String[] args) {    ApplicationContext context = new ClassPathXmlApplicationContext("beans-back.xml");    BackOffice backOffice = (BackOffice) context.getBean("backOffice");    Mail mail = backOffice.receiveMail();    System.out.println("Mail #" + mail.getMailId() + " received");   }  }

运行FrontDeskMain之后,发送消息你可以简单的通过访问http://127.0.0.1:8161/admin/queueGraph.jsp和http://127.0.0.1:8161/admin/queues.jsp观察发生的情况。再运行BackOfficeMain观察这两个页面的变化。

 
来自:http://my.oschina.net/fengshuzi/blog/346303