Spring对JMS的支持

  • 关于JMS的基础知识请参阅一篇写的简洁漂亮的文章,这篇文章将JMS的基本概念,以及JMS中主要类都介绍了。
  • 关于JMS和AMQP的区别请参照这篇文章AMQP相对于JMS是一种跨语言的通用的协议

    下面开始介绍Spring对JMS的支持

    概括介绍

    Spring 提供了 JMS集成框架来简化JMS API的使用,就像Spring针对JDBC API所做的那样。
    JMS大体上可以分为两个功能区,生产和消费消息。JmsTemplate可以用来消息生产和同步消息接收。对于类似于Java EE的消息驱动实体风格的异步接收,Spring提供了许多消息监听容器来创建消息驱动的实体。Spring同样提供了声明的方式创建消息监听器。
    包org.springframework.jms.core提供使用JMS的核心功能。其中JMS 模板类,通过处理资源的创建和释放来简化JMS的使用,就像JdbcTemplate针对JDBC做的工作。它的设计原则和Spring其它模板类一样,针对一般的操作使用辅助方法,对于复杂的操作将实际的工作委托给用户的回调接口来实现。JMS就是遵循了这一设计原则。JMS模板为发送小和同步消费消息提供了不同的方便方法,将JMS session和消息生产者暴露给用户。

包org.springframework.jms.support 中提供了 JMSException 异常转换功能。装换将JMS中检核异常转换为相应的非检核异常。如果没有找到相应的映射异常,则将异常归为UncategorizedJmsException。我们看一下代码:

package org.springframework.jms;

/**
 * Runtime exception mirroring the JMS MessageFormatException.
 *
 * @author Mark Pollack
 * @since 1.1
 * @see javax.jms.MessageFormatException
 */
@SuppressWarnings("serial")
public class MessageFormatException extends JmsException {

    public MessageFormatException(javax.jms.MessageFormatException cause) {
        super(cause);
    }

}

包org.springframework.jms.support.converter 提供MessageConverter抽象来完成Java对象和JMS消息之间的转换。

public interface MessageConverter {

    /**
     * Convert a Java object to a JMS Message using the supplied session
     * to create the message object.
     * @param object the object to convert
     * @param session the Session to use for creating a JMS Message
     * @return the JMS Message
     * @throws javax.jms.JMSException if thrown by JMS API methods
     * @throws MessageConversionException in case of conversion failure
     */
    Message toMessage(Object object, Session session) throws JMSException, MessageConversionException;

    /**
     * Convert from a JMS Message to a Java object.
     * @param message the message to convert
     * @return the converted Java object
     * @throws javax.jms.JMSException if thrown by JMS API methods
     * @throws MessageConversionException in case of conversion failure
     */
    Object fromMessage(Message message) throws JMSException, MessageConversionException;

}

包org.springframework.jms.support.destination中为管理JMS destination提供了不同的策略,例如为存储在JNDI中的destination提供了服务定位类。

包org.springframework.jms.annotation provides提供了注解驱动的技术@JmsListener。
包 org.springframework.jms.config 中提供了jms命名空间解析,以及java来配置监听容器和配置监听点。

public class JmsNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        registerBeanDefinitionParser("listener-container", new JmsListenerContainerParser());
        registerBeanDefinitionParser("jca-listener-container", new JcaListenerContainerParser());
        registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenJmsBeanDefinitionParser());
    }

}

最后包org.springframework.jms.connection中提供了ConnectionFactory的实现,在单机应用中很有用。它同样提供了Spring中 PlatformTransactionManager的实现(这里面叫做JmsTransactionManager),这样JMS就可以作为事务资源集成进Spring的事务管理系统中。

使用Spring JMS

JmsTemplate

JmsTemplate是核心包中的中心类。它在发送和同步接收消息的时候处理资源的创建和释放,从而简化JMS的使用。使用JmsTemplate只需要实现一些回调接口满足一些高层次的联系。MessageCreator回调接口中使用的Session是JmsTemplate中调用回调接口时的Session。
为了JMS API的复杂应用,SessionCallback为用户提供JMS session。ProducerCallback为用户提供JMS Session和MessageProducer。
JMS API中暴露了两种类型的发送方法:

    void send(Message message) throws JMSException;

    void send(Message message, int deliveryMode, int priority, long timeToLive)
        throws JMSException;

其实第一种使用默认值。
由于在JmsTemplate中有许多发送方法,所以在JmsTemplate中这些参数以属性的形式存在,从而避免在发送方法中重复出现。同样类似,同步接收超时时间通过setReceiveTimeout属性设置。
一些JMS提供商允许通过配置ConnectionFactory的方式来指定QOS 的默认值,这样MessageProducer的方法send(Destination destination, Message message)会使用不同的QOS 默认值而不是使用JMS 规范中的值。为了针对QOS 值进行一致性的管理,JmsTemplate 需要设置isExplicitQosEnabled 属性为真来启用自身QOS 值。
为了方便起见,JmsTemplate 同样暴露基础的请求响应操作,允许发送消息,在一个临时队列上等待临时队列,这个队列,作为这个操作的一部分。

注意
JmsTemplate 一旦配置之后就是线程安全的。这很重要,意味着你可以配置一个JmsTemplate 实例,然后将它注入给多个使用者。要清楚JmsTemplate 是有状态的,它持有一个ConnectionFactory,但是这个状态不是会话状态。

在Spring Framework 4.1中,JmsMessagingTemplate 构建在JmsTemplate 基础之上,与消息抽象进行集成,例如org.springframework.messaging.Message。这允许你以通用的方式创建消息。

Connections

JmsTemplate需要引用ConnectionFactory。这个ConnectionFactory是JMS规范的一部分,他是使用JMS的入口。客户端应用使用它创建与JMS提供者的连接,并且配置了各种各样的配置参数,一些参数是提供者规定的例如SSL配置选项。

缓存消息资源

标准的API涉及到许多创建中间对象。为了发送一个消息,涉及到下面这些操作

ConnectionFactory->Connection->Session->MessageProducer->send

在ConnectionFactory 合Send操作之间涉及到三个中间对象的创建与销毁。为了优化资源使用和提供性能,提供了ConnectionFactory 的两个实现。

SingleConnectionFactory

Spring提供了这样一个实现SingleConnectionFactory,他会再调用createConnection()的时候返回同一个连接,并且会忽略掉close()方法。这在测试环境和单机环境中很有用,所以同一个连接可以被多个JmsTemplate 调用,这些调用可能跨越多个事务。SingleConnectionFactory 持有一个标准ConnectionFactory的引用,这个ConnectionFactory通常来自JNDI。

CachingConnectionFactory

CachingConnectionFactory 继承了SingleConnectionFactory 的功能,并且添加了 Sessions, MessageProducers, 和MessageConsumers的缓存。初始的缓存大小设置为1,使用sessionCacheSize 来增加缓存session的大小。注意实际上会话缓存的大小大于session缓存数目,这取决于告知模式,所以在sessionCacheSize 大小设置为1时,实际上会有4个session实例,每个告知模式都会有一个。MessageProducers和MessageConsumers 缓存在他们的session中,同时在缓存的时候回考虑生产者和消费者的唯一属性。MessageProducers 基于destination进行缓存。MessageConsumers 基于destination、selector、非本地发送标识和持久化订阅名称的组合。

管理Destination

Destinations如同ConnectionFactories是JMS管理的对象,可以再JNDI中进行存储和获取当配置Spring应用上下文的时候,你可以使用JNDI工厂类JndiObjectFactoryBean 或者<jee:jndi-lookup> 对JMS destination对象进行依赖注入。然而,当你的应用中有大量的destination的时候或者需要JMS提供者的一些高级destination管理的功能这一策略很麻烦。例如这样的一个高级功能:创建动态的destinations 和支持destination命名的层级关系。JmsTemplate 将destination的解析委托给DestinationResolver接口。DynamicDestinationResolver 是JmsTemplate 使用的默认实现,这一实现包括动态解析destination。同事提供了JndiDestinationResolver实现来完成JNDI中destination的定位,并且可以选择性的回落到DynamicDestinationResolver的行为。
通常在JMS应用中destination只有在运行的时候能够定下来,所以在应用部署的时候不能进行管理创建。这通常是因为在多个系统组件之间destination的创建存在一定的命名约定。尽管动态destination的创建不是JMS规范的一部分,大多数的供应商提供了这一功能

Dynamic destinations are created with
a name defined by the user which differentiates them from temporary destinations and are often not
registered in JNDI. The API used to create dynamic destinations varies from provider to provider since
the properties associated with the destination are vendor specific. However, a simple implementationchoice that is sometimes made by vendors is to disregard the warnings in the JMS specification and to
use the TopicSession method createTopic(String topicName) or the QueueSession method
createQueue(String queueName) to create a new destination with default destination properties.
Depending on the vendor implementation, DynamicDestinationResolver may then also create a
physical destination instead of only resolving one.
The boolean property pubSubDomain is used to configure the JmsTemplate with knowledge of what
JMS domain is being used. By default the value of this property is false, indicating that the point-topoint domain, Queues, will be used. This property used by JmsTemplate determines the behavior of
dynamic destination resolution via implementations of the DestinationResolver interface.
You can also configure the JmsTemplate with a default destination via the property
defaultDestination. The default destination will be used with send and receive operations that do
not refer to a specific destination.

Message Listener Containers

Transaction management

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值