天天看点

Spring 对JMS的支持

Spring提供了一个用于简化JMS API使用的抽象框架,用户利用Spring使用JMS可以不用关心connection factory,session等资源的管理.类似于对JDBC的抽象,Spring提供了一个

JmsTemplate类,抽象了操作JMS都必须做的公共步骤,留下了callback方法给用户去实现,如提供消息的真正内容等.

本文主要讲解一下怎么使用Spring来发送消息,接受消息和异步接受消息(MessageListener).

一,发送消息:

1,通过

JmsTemplate的

send方法和提供一个

MessageCreator的实现的最简单应用:

JAVA类(用配置文件中配置的默认的queue):

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>
           

继续阅读