Spring提供了一个用于简化JMS API使用的抽象框架,用户利用Spring使用JMS可以不用关心connection factory,session等资源的管理.类似于对JDBC的抽象,Spring提供了一个JmsTemplate类,抽象了操作JMS都必须做的公共步骤,留下了callback方法给用户去实现,如提供消息的真正内容等.
本文主要讲解一下怎么使用Spring来发送消息,接受消息和异步接受消息(MessageListener).
一,发送消息:
1,通过JmsTemplate的
send方法和提供一个MessageCreator的实现的最简单应用:
JAVA类:
public class JMSsenderBean {
private JmsTemplate jmsTemplate;
public void simpleSend() {
this.jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("hello queue world");
}
});
}
配置:(本例在weblogic上配置了JMS服务)
<beans>
<bean id="JMSsenderBean" class="com.test.spring.jms.JMSsenderBean">
<property name="jmsTemplate">
<ref local="jmsTemplate"></ref>
</property>
<property name="queue">
<ref local="destination1"></ref>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jms/jmsconf</value>
</property>
<property name="jndiTemplate">
<ref local="jndiTemplate"></ref>
</property>
</bean>
<bean id="destination1" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jms/jmsq1</value>
</property>
<property name="jndiTemplate">
<ref local="jndiTemplate"></ref>
</property>
</bean>
<bean id="destination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jms/jmsq</value>
</property>
<property name="jndiTemplate">
<ref local="jndiTemplate"></ref>
</property>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref local="connectionFactory" />
</property>
<property name="defaultDestination">
<ref local="destination" />
</property>
</bean>
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">
weblogic.jndi.WLInitialContextFactory
</prop>
<prop key="java.naming.provider.url">
t3://localhost:7001
</prop>
<!--
<prop key="java.naming.security.authentication"> weblogic </prop>
<prop key="java.naming.security.credentials"> security </prop>
-->
</props>
</property>
</bean>
</beans>
2,在发送的时候指定Queue:(配置同上)
public void withQSend() {
this.jmsTemplate.send(queue, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("hello queue world to jmsq1");
}
});
}
3,通过JmsTemplate的
convertAndSend方法和提供一个MessageConverter的实现来将传入的对象转成message:
public void convertAndSend(MsgObject object) {
this.jmsTemplate.setMessageConverter(new MyMessageConverter());
this.jmsTemplate.convertAndSend(object);
}
public class MyMessageConverter implements MessageConverter{
public Object fromMessage(Message message) throws JMSException, MessageConversionException {
TextMessage msg = (TextMessage)message;
MsgObject obj = new MsgObject();
obj.setName("from message");
return obj;
}
public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
MsgObject obj = (MsgObject)object;
return session.createTextMessage("from Object MsgObject " + obj.getName() + " " + obj.getAge());
}
}
4,实现SessionCallback,利用
JmsTemplate的execute方法来对session进行操作,可以发送和接受消息.
public void sessionCbkSend() {
this.jmsTemplate.execute(new MySessionCallback(this.jmsTemplate));
}
public class MySessionCallback implements SessionCallback{
private JmsTemplate jmsTemplate;
public MySessionCallback(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public Object doInJms(Session session) throws JMSException {
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
System.out.println("..............");
return session.createTextMessage("message from session back");
}
});
System.out.println("..............");
return null;
}
}
二,接受消息
public void receiveMsg() {
TextMessage msg = (TextMessage)this.jmsTemplate.receive();
try {
System.out.println(msg.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
三,异步接受消息:实现MessageListener,配置listenerContainer,默认情况下,Spring容器启动后,Listener就会启动.
public class ExampleListener implements MessageListener {
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
System.out.println(((TextMessage) message).getText());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
} else {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
}
配置
<bean id="messageListener" class="com.test.spring.jms.ExampleListener">
</bean>
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="destination" />
<property name="messageListener" ref="messageListener" />
</bean>
通过listenerContainer的stop和shutdown方法停止服务.
jmsContainer.stop();
jmsContainer.shutdown();
对listener的事务管理:
如果是本地事务,只需要设置listenerContainer的sessionTransacted就可以了.
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
...
<property name="sessionTransacted" value="true"/>
</bean>
如果在onMessage中还有对其他资源,如数据库的操作,需要使用JTA来控制全局事务.
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
...
<property name="transactionManager" ref="transactionManager" />
</bean>