`

Spring JMS接收消息

阅读更多

一.同步接收

        虽然JMS一般都和异步处理相关,但它也可以同步的方式使用消息。可重载的 receive(..) 方法提供了这种功能。在同步接收中,接收线程被阻塞直至获得一个消息,有可能出现线程被无限阻塞的危险情况。属性 receiveTimeout 指定了接收器可等待消息的延时时间。

 

二.异步接收 - 消息驱动的POJO

        类似于EJB世界里流行的消息驱动Bean(MDB),消息驱动POJO(MDP)作为JMS消息的接收器。MDP的一个约束(但也请看下面的有关 javax.jms.MessageListener 类的讨论)是它必须实现 javax.jms.MessageListener 接口。另外当你的POJO将以多线程的方式接收消息时必须确保你的代码是线程-安全的。

        以下是MDP的一个简单实现:

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class ExampleListener implements MessageListener {

    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            try {
                System.out.println(((TextMessage) message).getText());
            }
            catch (JMSException ex) {
                throw new RuntimeException(ex);
            }
        }
        else {
            throw new IllegalArgumentException("Message must be of type TextMessage");
        }
    }
}

        一旦你实现了 MessageListener 后就可以创建一个消息侦听容器。

        请看下面例子是如何定义和配置一个随Sping发行的消息侦听容器的(这个例子用 DefaultMessageListenerContainer)

<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageListener" class="jmsexample.ExampleListener" />

<!-- and this is the message listener container -->
<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>

        关于各个消息侦听容器实现的特色请参阅相关的Spring Javadoc文档。

 

三.SessionAwareMessageListener接口

        SessionAwareMessageListener 接口是一个Spring专门用来提供类似于JMS MessageListener的接口,也提供了从接收 Message 来访问JMS Session的消息处理方法。

package org.springframework.jms.listener;

public interface SessionAwareMessageListener {

    void onMessage(Message message, Session session) throws JMSException;
}

        如果你希望你的MDP可以响应所有接收到的消息(使用 onMessage(Message, Session) 方法提供的 Session)那么你可以选择让你的MDP实现这个接口(优先于标准的JMS MessageListener 接口)。所有随Spring发行的支持MDP的消息侦听容器都支持 MessageListener 或 SessionAwareMessageListener 接口的实现。要注意的是实现了 SessionAwareMessageListener 接口的类通过接口和Spring有了耦合。是否选择使用它完全取决于开发者或架构师。

        请注意 SessionAwareMessageListener 接口的 'onMessage(..)' 方法会抛出 JMSException异常。和标准JMS MessageListener 接口相反,当使用 SessionAwareMessageListener 接口时,客户端代码负责处理任何抛出的异常。

 

四.MessageListenerAdapter

        MessageListenerAdapter类是Spring的异步支持消息类中的不变类(final class):简而言之,它允许你几乎将任意 一个类做为MDP显露出来(当然有某些限制)。

        注意:如果你使用JMS 1.0.2 API,你将使用和 MessageListenerAdapter 一样功能的类MessageListenerAdapter102。

        考虑如下接口定义。注意虽然这个接口既不是从 MessageListener 也不是从 SessionAwareMessageListener 继承来得,但通过 MessageListenerAdapter 类依然可以当作一个MDP来使用。同时也请注意各种消息处理方法是如何根据他们可以接收并处理消息的内容来进行强类型匹配的。

public interface MessageDelegate {

    void handleMessage(String message);

    void handleMessage(Map message);

    void handleMessage(byte[] message);

    void handleMessage(Serializable message);
}
public class DefaultMessageDelegate implements MessageDelegate {
    // implementation elided for clarity...
}

        特别请注意,上面的 MessageDelegate 接口(上文中 DefaultMessageDelegate 类)的实现完全不依赖于JMS。它是一个真正的POJO,我们可以通过如下配置把它设置成MDP。

<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
    <constructor-arg>
        <bean class="jmsexample.DefaultMessageDelegate"/>
    </constructor-arg>
</bean>

<!-- and this is the message listener container... -->
<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>

        下面是另外一个只能处理接收JMS TextMessage 消息的MDP示例。注意消息处理方法是如何实际调用 'receive' (在 MessageListenerAdapter 中默认的消息处理方法的名字是 'handleMessage')的,但是它是可配置的(你下面就将看到)。注意 'receive(..)' 方法是如何使用强制类型来只接收和处理JMS TextMessage消息的。

public interface TextMessageDelegate {

    void receive(TextMessage message);
}
public class DefaultTextMessageDelegate implements TextMessageDelegate {
    // implementation elided for clarity...
}

        辅助的MessageListenerAdapter类配置文件类似如下:

<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
    <constructor-arg>
        <bean class="jmsexample.DefaultTextMessageDelegate"/>
    </constructor-arg>
    <property name="defaultListenerMethod" value="receive"/>
    <!-- we don't want automatic message context extraction -->
    <property name="messageConverter">
        <null/>
    </property>
</bean>

        请注意,如果上面的 'messageListener' 收到一个不是 TextMessage 类型的JMS Message,将会产生一个 IllegalStateException 异常(随之产生的其他异常只被捕获而不处理)。

        MessageListenerAdapter还有一个功能就是如果处理方法返回一个非空值,它将自动返回一个响应 消息。

请看下面的接口及其实现:

public interface ResponsiveTextMessageDelegate {

    // notice the return type...
    String receive(TextMessage message);
}
public class DefaultResponsiveTextMessageDelegate implements ResponsiveTextMessageDelegate {
    // implementation elided for clarity...
}

        如果上面的 DefaultResponsiveTextMessageDelegate 和 MessageListenerAdapter 联合使用,那么任意从执行 'receive(..)' 方法返回的非空值都将(缺省情况下)转换成一个 TextMessage。这个返回的 TextMessage 将被发送到原来的 Message 中JMS Reply-To属性定义的 目的地(如果存在),或者是 MessageListenerAdapter 设置(如果配置了)的缺省 目的地;如果没有定义 目的地,那么将产生一个 InvalidDestinationException 异常(此异常将不会只被捕获而不处理,它 将沿着调用堆栈上传)。

 

五.事务中的消息处理

        在消息监听器的调用中使用事务只需要重新配置监听器容器。

        通过监听器容器定义中的 sessionTransacted 标记可以轻松的激活本地资源事务。每次消息监听器的调用都在激活的JMS事务中执行,执行失败时,消息接收将发生回滚。这个本地事务还将包含响应信息的发送(通过 SessionAwareMessageListener),但其它资源的操作(例如访问数据库)是独立的。经常会发生类似于数据库处理已提交但消息处理提交失败的情况,因此需要在监听器的实现中进行重复消息的检测。

<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="destination" ref="destination"/>
    <property name="messageListener" ref="messageListener"/>
    <property name="sessionTransacted" value="true"/>
</bean>

        当参与外部管理的事务时,你需要使用支持外来事务的监听器容器:通常是DefaultMessageListenerContainer 来配置事务管理器。

        参与XA事务时,消息监听器容器需要配置 JtaTransactionManager(默认会委托给J2EE服务器事务子系统)。注意以下JMS ConnectionFactory需要具有XA能力并注册JTA事务协调器!(参考你所使用的J2EE服务器中JNDI资源的配置。)这样,消息接收就像数据库访问一样作为同一个事务的一部分(具有统一提交的语义,仅仅增加了XA事务日志的额外开销)。

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

        然后你只需要把它添加到早先配置好的容器中。这个容器将处理剩下的事情。

<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="destination" ref="destination"/>
    <property name="messageListener" ref="messageListener"/>
    <property name="transactionManager" ref="transactionManager"/>
</bean>

 

文章来源:http://www.shouce.ren/api/spring2.5/ch19s04.html

分享到:
评论

相关推荐

    Spring发送接收JMS消息

    本篇文章将深入探讨如何使用Spring进行JMS消息的发送和接收。 ### 1. JMS概述 JMS是一种中间件协议,它定义了生产、存储和消费消息的标准接口。JMS提供两种类型的消息模型:点对点(Point-to-Point, P2P)和发布/...

    SpringJMS示例代码

    SpringJMS提供了事务支持,可以在发送或接收消息时启用JMS事务,确保消息传递的可靠性。 9. **错误处理和异常传播** SpringJMS允许开发者捕获和处理JMS异常,例如消息无法发送或接收时,可以通过Spring的异常处理...

    spring_jms

    Spring JMS(Java Message Service)是Spring框架的一部分,专门用于集成JMS消息传递系统,以实现异步通信和解耦应用程序组件。在这个入门级实例中,我们将探讨如何使用Maven、Spring和ActiveMQ来构建一个简单的...

    Spring JMS 消息处理-基于JNDI

    7. **实战示例**:最后,博主会提供一个实际的示例,展示如何在一个简单的Spring应用中集成JMS,包括创建JNDI资源、配置Spring容器以及测试发送和接收消息。 通过学习这篇博客,开发者可以了解到如何利用Spring JMS...

    Spring JMS使异步消息变得简单.doc

    Spring JMS通过提供`JmsTemplate`类,将这些繁琐的步骤封装起来,开发者只需要调用几个简单的API就可以发送和接收消息,极大地提高了开发效率。 使用Spring JMS的一个关键优势在于其灵活性。`JmsTemplate`允许你...

    spring-jms入门

    Spring-JMS是Spring框架的一部分,专门用于处理Java消息服务(JMS)的集成。它提供了一个简单的API,使得开发者能够方便地在应用中使用消息传递功能。本文将深入探讨Spring-JMS的基础知识,包括它的核心概念、配置...

    tomcat spring jms 异步消息传递入门实例

    本教程将带你逐步了解如何利用Tomcat、Spring和JMS(Java Message Service)构建一个简单的异步消息传递入门实例。 首先,让我们来理解一下核心组件: 1. **Tomcat**:这是一个流行的开源Java Servlet容器,用于...

    Spring+JMS+消息处理

    - **JMS Template(模板类)**:`JmsTemplate`是Spring JMS提供的核心组件之一,它简化了JMS消息的发送和接收过程。该模板类负责创建和管理JMS会话、连接及事务,并提供了多个方法用于发送消息或接收消息。 - **`...

    Spring JMS消息处理-不基于JNDI

    Spring JMS通过提供Template类简化了这个过程,它封装了发送和接收消息的低级细节。 在不使用JNDI的情况下配置Spring JMS,我们需要直接实例化ConnectionFactory和Destination对象。ConnectionFactory是用于创建与...

    Spring-JMS把企业消息处理变容易.doc

    模板类提供了发送消息、同步接收消息以及访问JMS会话和消息生产者的辅助方法。在需要更复杂操作时,模板类会将控制权交给用户实现的回调接口,如`MessageCreator`和`SessionCallback`,以实现自定义的行为。 `org....

    Spring+weblogic接收JMS消息

    标题"Spring+weblogic接收JMS消息"涉及到的核心知识点是Spring框架与WebLogic Server之间的整合,以及如何利用Spring来处理JMS消息。下面将详细讲解这两个方面的内容。 1. **Spring对JMS的支持**: - Spring通过`...

    Java网络编程--基于Spring的JMS编程

    在Java中,Spring框架提供了强大而灵活的支持,使得开发人员能够轻松地实现基于Java消息服务(JMS)的网络编程。JMS是一个标准接口,它允许应用程序创建、发送、接收和读取消息,这些消息可以在不同的应用之间传递,...

    jms整合spring工程

    - **发送和接收消息**:通过Spring的JmsTemplate发送消息,通过MessageListener或MessageDriven POJO(MDP)接收消息。 4. **项目结构与文件** - **JmsSpring**:这个目录可能包含了整个工程的源代码,包括配置...

    spring jms tomcat 异步消息传递入门实例

    通过`org.springframework.jms.core.JmsTemplate`,我们可以方便地发送和接收消息。配置JMS模板,需要指定ConnectionFactory,它是连接JMS提供者的桥梁。Spring还支持声明式事务管理,确保消息传输的可靠性。 2. **...

    springjms的demo

    Spring对JMS提供了很好的支持,可以通过JmsTemplate来方便地实现消息服务。本例通过activeMQ服务器模拟了消息的发送与接收。需要注意的是,activeMQ的运行依赖jdk的环境,而且对jdk的版本也有要求,我用的是jdk1.6+...

    spring-jms源码

    MessageTemplate是Spring JMS提供的主要操作消息的模板类,它提供了一系列发送和接收消息的方法,如send、receive等,简化了JMS API的使用。JmsTemplate则是MessageTemplate的扩展,提供了更多的配置选项和操作方法...

    Spring JMS

    JMS 模板被用来发送和接收 JMS 消息。Spring 采用回调机制对 JMS 信息传递进行协调。MessageCreator 回调接口用来创建 JMS 消息。 Spring JMS 提供了一个简洁的方式来使用 JMS,简化了 JMS 的使用,使得开发者可以...

Global site tag (gtag.js) - Google Analytics