1. 概述:Spring提供了一個用於簡化JMS API使用的抽象框架,而且對用戶屏蔽了JMS API中1.0.2和1.1版本的差別。
JMS的功能大體上分爲兩塊,叫作消息製造和消息消耗。JmsTemplate 用於製造消息和同步消息接收。咱們今天就用JmsTemplate實現同步的消息接受。
使用JMS發(接)消息的步驟:
1)建立鏈接工廠
2)使用鏈接工廠建立鏈接
3)使用鏈接建立會話
4)獲取一個目的地
5)使用會話和目的地建立消息生產者(消息消費者)
6)使用鏈接建立一個須要發送的消息類型實例
7)使用鏈接的一個隊列發送器或主題公佈器,使用發送器或者主題器發送消息(接受消息)
spring中的JmsTemplate實現了對jms的一些封裝,內部提供了不少的方法,咱們只須要實現定義的回調接口便可。JmsTemplate繼承自JmsAccessor,在JmsAccessor中有ConnectionFactory的定義,而JmsTemplate自己的構造方法也有對ConnectionFactory的封裝:
- public JmsTemplate(ConnectionFactory connectionFactory) {
- this();
- setConnectionFactory(connectionFactory);
- afterPropertiesSet();
- }
public JmsTemplate(ConnectionFactory connectionFactory) {
this();
setConnectionFactory(connectionFactory);
afterPropertiesSet();
}
因此,咱們有兩種方式注入ConnectionFactory,本文咱們採用構造方法的方式。
spring_jms.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"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
-
- <!-- 這裏咱們用構造方法注入 connectionFactory-->
- <bean id = "jmsTemplate" class = "org.springframework.jms.core.JmsTemplate">
- <constructor-arg ref="connectionFactory"></constructor-arg>
- </bean>
-
- <!-- 使用activemq中的鏈接工廠,提供一個brokerUrl,這裏表示本地 -->
- <bean id = "connectionFactory" class = "org.apache.activemq.ActiveMQConnectionFactory">
- <property name="brokerURL" value="vm://localhost" />
- </bean>
-
- <!-- 使用activemq中的點對點消息模型,隨意指定一個地址 -->
- <bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
- <constructor-arg value="test/queue"/>
- </bean>
-
- </beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 這裏咱們用構造方法注入 connectionFactory-->
<bean id = "jmsTemplate" class = "org.springframework.jms.core.JmsTemplate">
<constructor-arg ref="connectionFactory"></constructor-arg>
</bean>
<!-- 使用activemq中的鏈接工廠,提供一個brokerUrl,這裏表示本地 -->
<bean id = "connectionFactory" class = "org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost" />
</bean>
<!-- 使用activemq中的點對點消息模型,隨意指定一個地址 -->
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="test/queue"/>
</bean>
</beans>
MessageCreator 回調接口經過JmsTemplate中調用代碼提供的Session來建立一條消息。
看一下MessageCreator接口:
- public interface MessageCreator {
-
- Message createMessage(Session session) throws JMSException;
-
- }
public interface MessageCreator {
Message createMessage(Session session) throws JMSException;
}
那麼,咱們來實現發送和接受消息DummyJms類
- public class DummyJms {
-
- public static void main(String[] args) throws Exception{
- ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
- JmsTemplate jmsTemplate = (JmsTemplate)context.getBean("jmsTemplate");
- Destination destination = (Destination)context.getBean("destination");
-
- jmsTemplate.send(destination, new MessageCreator(){
-
- public Message createMessage(Session session)
- throws JMSException {
- return session.createTextMessage("send message ");
- }
-
-
- });
-
- TextMessage msg = (TextMessage)jmsTemplate.receive(destination);
- System.out.println("receive message = " + msg.getText());
-
- }
-
- }
public class DummyJms {
public static void main(String[] args) throws Exception{
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
JmsTemplate jmsTemplate = (JmsTemplate)context.getBean("jmsTemplate");
Destination destination = (Destination)context.getBean("destination");
jmsTemplate.send(destination, new MessageCreator(){
public Message createMessage(Session session)
throws JMSException {
return session.createTextMessage("send message ");
}
});
TextMessage msg = (TextMessage)jmsTemplate.receive(destination);
System.out.println("receive message = " + msg.getText());
}
}
輸出結果:
receive message = send message
但是咱們並無看到的像前文描述的那那些建立消息生產者,消息消費者的一些東西。繼續分析,咱們能夠看一下,
jmsTemplate.send(Destination destination,MessageCreator messageCreator)這裏到底作了什麼,可讓咱們不費吹灰之力,就能夠實現消息的發送。JmsTemplate源代碼:
- public void send(final Destination destination, final MessageCreator messageCreator) throws JmsException {
- execute(new SessionCallback<Object>() {
- public Object doInJms(Session session) throws JMSException {
- doSend(session, destination, messageCreator);
- return null;
- }
- }, false);
- }
public void send(final Destination destination, final MessageCreator messageCreator) throws JmsException {
execute(new SessionCallback<Object>() {
public Object doInJms(Session session) throws JMSException {
doSend(session, destination, messageCreator);
return null;
}
}, false);
}
JmsTemplate實現了JmsOperations接口,在JmsOperations裏有
- <T> T execute(SessionCallback<T> action) throws JmsException;
<T> T execute(SessionCallback<T> action) throws JmsException;
的定義。
那麼這個SessionCallback接口是什麼呢?它也爲用戶提供了JMS session。
Java代碼
public interface SessionCallback<T> {
-
- T doInJms(Session session) throws JMSException;
-
- }
public interface SessionCallback<T> {
T doInJms(Session session) throws JMSException;
}
繼續往下看。doSend方法:
Java代碼
protected void doSend(Session session, Destination destination, MessageCreator messageCreator)
- throws JMSException {
-
- Assert.notNull(messageCreator, "MessageCreator must not be null");
- MessageProducer producer = createProducer(session, destination);
- try {
- Message message = messageCreator.createMessage(session);
- if (logger.isDebugEnabled()) {
- logger.debug("Sending created message: " + message);
- }
- doSend(producer, message);
-
- if (session.getTransacted() && isSessionLocallyTransacted(session)) {
-
- JmsUtils.commitIfNecessary(session);
- }
- }
- finally {
- JmsUtils.closeMessageProducer(producer);
- }
- }
protected void doSend(Session session, Destination destination, MessageCreator messageCreator)
throws JMSException {
Assert.notNull(messageCreator, "MessageCreator must not be null");
MessageProducer producer = createProducer(session, destination);
try {
Message message = messageCreator.createMessage(session);
if (logger.isDebugEnabled()) {
logger.debug("Sending created message: " + message);
}
doSend(producer, message);
// Check commit - avoid commit call within a JTA transaction.
if (session.getTransacted() && isSessionLocallyTransacted(session)) {
// Transacted session created by this template -> commit.
JmsUtils.commitIfNecessary(session);
}
}
finally {
JmsUtils.closeMessageProducer(producer);
}
}
createProducer()方法又調用了doCreateProducer(),實際的消息生產者在這裏。
protected MessageProducer doCreateProducer(Session session, Destination destination) throws JMSException {
- return session.createProducer(destination);
- }
protected MessageProducer doCreateProducer(Session session, Destination destination) throws JMSException {
return session.createProducer(destination);
}
在這裏,咱們看到了,spring建立了消息的發送者,關閉鏈接的一些操做。到這裏,你們就明白了,spring內部處理Jms消息的過程了吧(消息的接受也是同樣)。 注:本文使用spring3.0和activemq5.2版本。