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观察这两个页面的变化。