`
newleague
  • 浏览: 1505058 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

JMS支持

    博客分类:
  • JMS
 
阅读更多

14.1. 介绍

Spring提供一个用于简化JMS API使用的抽象层框架,并且对用户屏蔽JMS API中从1.0.2到1.1版本之间的不同。

JMS大体上被分为两个功能块,消息生产和消息消费。在J2EE环境,由消息驱动的bean提供了异步消费消息的能力 。而在独立的应用中,则必须创建MessageListener或ConnectionConsumer来消费消息。 JmsTemplate的主要功能就是产生消息。Spring的未来版本将会提供,在一个独立的环境中处理异步消息。

org.springframework.jms.core包提供使用JMS的核心功能。 就象为JDBC提供的JdbcTemplate一样, 它提供了JMS模板类来处理资源的创建和释放以简化JMS的使用。 这个Spring的模板类的公共设计原则就是通过提供helper方法去执行公共的操作, 以及将实际的处理任务委派到用户实现的回调接口上,从而以完成更复杂的操作。 JMS模板遵循这样的设计原则。这些类提供众多便利的方法来发送消息、异步地接收消息、 将JMS会话和消息产生者暴露给用户。

org.springframework.jms.support包提供JMSException的转换功能。 它将checked JMSException级别转换到一个对应的unchecked异常级别, 任何checked的javax.jms.JMSException异常的子类都被包装到unchecked的UncategorizedJmsException。 org.springframework.jms.support.converter 包提供一个MessageConverter的抽象进行Java对象和JMS消息之间的转换。 org.springframework.jms.support.destination提供多种管理JMS目的地的策略, 例如为存储在JNDI中的目的地提供一个服务定位器。

最后,org.springframework.jms.connection包提供一个适合在独立应用中使用的 ConnectionFactory的实现。它还为JMS提供了一个Spring的PlatformTransactionManager的实现。 这让JMS作为一个事务资源和Spring的事务管理机制可以集成在一起使用。

14.2. 域的统一

JMS主要发布了两个规范版本,1.0.2和1.1。JMS1.0.2定义了两种消息域, 点对点(队列)和发布/订阅(主题)。 JMS1.0.2的API为每个消息领域提供了类似的类体系来处理这两种不同的消息域。 结果,客户端应用在使用JMS API时要了解是在使用哪种消息域。 JMS 1.1引进了统一域的概念来最小化这两种域之间功能和客户端API的差别。 举个例子,如果你使用的是一个JMS 1.1的消息供应者, 你可以使用同一个Session事务性地在一个域接收一个消息后并且从另一个域中产生一个消息。

JMS 1.1的规范发布于2002年4月,并且在2003年11月成为J2EE 1.4的一个组成部分, 结果,现在大多数使用的应用服务器只支持JMS 1.0.2的规范.

14.3. JmsTemplate

这里为JmsTemplate提供了两个实现。JmsTemplate类使用JMS 1.1的API, 而子类JmsTemplate102使用了JMS 1.0.2的API。

使用JmsTemplate的代码只需要实现规范中定义的回调接口。 在JmsTemplate中通过调用代码让MessageCreator回调接口用所提供的会话(Session)创建消息。 然而,为了顾及更复杂的JMS API应用,回调接口SessionCallback将JMS会话提供给用户, 并且暴露Session和MessageProducer。

JMS API暴露两种发送方法,一种接受交付模式、优先级和存活时间作为服务质量(QOS)参数, 而另一种使用缺省值作为QOS参数(无需参数)方式。由于在JmsTemplate中有多种发送方法, QOS参数用bean属性进行暴露设置,从而避免在一系列发送方法中重复。同样地, 使用setReceiveTimeout属性值来设置用于异步接收调用的超时值。

某些JMS供应者允许通过ConnectionFactory的配置来设置缺省的QOS值。 这样在调用MessageProducer的发送方法send(Destination destination, Message message) 时效率更高,因为调用时直接会使用QOS缺省值,而不再用JMS规范中定义的值。 所以,为了提供对QOS值域的统一管理,JmsTemplate必须通过设置布尔值属性isExplicitQosEnabled 为true,使它能够使用自己的QOS值。

14.3.1. ConnectionFactory

JmsTemplate请求一个对ConnectionFactory的引用。 ConnectionFactory是JMS规范的一部分,并被作为使用JMS的入口。 客户端应用通常作为一个工厂配合JMS提供者去创建连接,并封装一系列的配置参数, 其中一些是和供应商相关的,例如SSL的配置选项。

当在EJB内使用JMS时,供应商提供JMS接口的实现,以至于可以参与声明式事务的管理, 提供连接池和会话池。为了使用这个实现,J2EE容器一般要求你在EJB或servlet部署描述符中将JMS连接工厂声明为 resource-ref。为确保可以在EJB内使用JmsTemplate的这些特性, 客户应用应当确保它能引用其中的ConnectionFactory实现。

Spring提供ConnectionFactory接口的一个实现,SingleConnectionFactory, 它将在所有的createConnection调用中返回一个相同的连接, 并忽略close的调用。这在测试和独立的环境中相当有用, 因为同一个连接可以被用于多个JmsTemplate调用以跨越多个事务。 SingleConnectionFactory接受一个通常来自JNDI的标准ConnectionFactory的引用。

14.3.2. 事务管理

Spring为单个JMS ConnectionFactory提供一个JmsTransactionManager来管理事务。 它允许JMS应用可以利用第7章中描述的Spring的事务管理特性。JmsTransactionManager 从指定的ConnectionFactory将一个Connection/Session对绑定到线程。然而,在一个J2EE环境, ConnectionFactory将缓存连接和会话,所以被绑定到线程的实例依赖于缓存的行为。 在一个独立的环境,使用Spring的SingleConnectionFactory将导致使用单独的JMS连接, 而且每个连接都有自己的会话。JmsTemplate也能和JtaTransactionManager 以及XA-capable的JMS ConnectionFactory一起使用以完成分布式事务。

当使用JMS API从连接创建一个Session时,跨越管理性和非管理性事务的复用代码可能会让人困惑。这是因为JMS API只提供一个工厂方法来创建会话,并且它要求事务和确认模式的值。在受管理的环境下,由事务结构环境负责设置这些值,这样在供应商包装的JMS连接中可以忽略这些值。当在一个非管理性的环境中使用JmsTemplate时,你可以通过使用属性SessionTransactedSessionAcknowledgeMode来指定这些值。当在JmsTemplate中使用PlatformTransactionManager时,模板将一直被赋予一个事务性JMS会话。

14.3.3. Destination管理

Destination,象ConnectionFactories一样,是可以在JNDI中进行存储和提取的JMS管理对象。当配置一个Spring应用上下文,可以使用JNDI工厂类JndiObjectFactoryBean在你的对象引用上执行依赖注入到JMS Destination。然而,如果在应用中有大量的Destination,或者JMS供应商提供了特有的高级Destination管理特性,这个策略常常显得很笨重。高级Destination管理的例子如创建动态destination或支持destination的命名层次。JmsTemplate将destination名字到JMS destination对象的解析委派到一个DestinationResolver接口的实现。DynamicDestinationResolverJmsTemplate 使用的默认实现,并且提供动态destination解析。同时JndiDestinationResolver作为JNDI包含的destination的服务定位器,并且可选择地退回来使用DynamicDestinationResolver提供的行为。

相当常见的是在一个JMS应用中所使用的destination只有在运行时才知道,因此,当一个应用被部署时,它不能被创建。这经常是因为交互系统组件之间的共享应用逻辑是在运行时按照已知的命名规范创建destination。虽然动态destination的创建不是JMS规范的一部分,但是许多供应商已经提供了这个功能。用户为所建的动态destination定义名字,这样区别于来临时destination,并且动态destination不会被注册到JNDI中。创建动态destination所使用的API在不同的供应商之间差别很大,因为destination所关联的属性是供应商特有的。然而,有时由供应商作出的一个简单的实现选择是忽略JMS规范中的警告,并使用TopicSession的方法createTopic(String topicName)或者QueueSession的方法createQueue(String queueName)来创建一个拥有默认属性的新destination。依赖于供应商的实现,DynamicDestinationResolver可能也能创建一个物理上的destination,而不是只是解析。

布尔属性PubSubDomain被用来配置JmsTemplate使用什么样的JMS域。这个属性的默认值是false,使用点到点的域,也就是队列。在1.0.2的实现中,这个属性值用来决定JmsTemplate将消息发送到一个队列还是主题。这个标志在1.1的实现中对发送操作没有影响。然而,在这两个实现中,这个属性决定了通过DestinationResolver的实现来解析动态destination的行为。

你还可以通过属性DefaultDestination配置一个带有默认destination的JmsTemplate。默认的destination被使用时,它的发送和接收操作不需要指定一个特定的destination。

14.4. 使用JmsTemplate

要开始使用JmsTemplate前,你需要选择JMS 1.0.2的实现,JmsTemplate102,还是JMS 1.1的实现,JmsTemplate。检查一下你的JMS供应者支持那个版本。

14.4.1. 发送消息

JmsTemplate包含许多有用的方法来发送消息。这些发送方法可以使用javax.jms.Destination对象指定destination,也可以使用字符串在JNDI中查找destination。没有destination参数的发送方法使用默认的destination。这里有个例子使用1.0.2的实现发送消息到一个队列。

import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.Session;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.JmsTemplate102;
import org.springframework.jms.core.MessageCreator;

public class JmsQueueSender {

  private JmsTemplate jt;

  private ConnectionFactory connFactory;

  private Queue queue;

  public void simpleSend() {
    jt = new JmsTemplate102(connFactory, false);
    jt.send(queue, new MessageCreator() {
      public Message createMessage(Session session) throws JMSException {
        return session.createTextMessage("hello queue world");
      }
    });
  }

  public void setConnectionFactory(ConnectionFactory cf) {
      connFactory = cf;
  }

  public void setQueue(Queue q) {
      queue = q;
  }

}
      

这个例子使用MessageCreator回调接口从所提供的会话对象中创建一个文本消息,并且通过一个ConnectionFactory的引用和指定消息域的布尔值来创建JmsTemplate。BeanFactory使用一个没有参数的构造方法和setConnectionFactory/Queue方法来用构造实例。simpleSend方法在下面修改为发送消息到一个主题而不是队列。

public void simpleSend() {
  jt = new JmsTemplate102(connFactory, true);
  jt.send(topic, new MessageCreator() {
     public Message createMessage(Session session) throws JMSException {
        return session.createTextMessage("hello topic world");
     }
  });
}     
      

当在应用上下文中配置JMS 1.0.2时,重要的是记得设定布尔属性 PubSubDomain的值以确定你是要发送到队列还是主题。

方法send(String destinationName, MessageCreator c)让你利用destination的名字发送消息。如果这个名字在JNDI中注册,你应当将模板中的DesinationResolver属性设置为JndiDestinationResolver的一个实例。

如果你创建JmsTemplate并指定一个默认的destination,send(MessageCreator c)发送消息到这个destination。

14.4.2. 同步接收

虽然JMS一般都是应用在异步操作,但它也可能同步接收消息。重载的receive方法就提供这个功能。在同步接收时,调用线程被阻塞直到收到一个消息。这是一个危险的操作,因为调用线程可能会被无限期的阻塞。receiveTimeout属性指定接收者在放弃等待一个消息前要等多久。

14.4.3. 使用消息转换器

为了更容易的发送域模式对象,JmsTemplate有多种将一个Java对象作为消息数据内容的发送方法。在JmsTemplate中重载方法convertAndSendreceiveAndConvert,可以将转换过程委派到MessageConverter接口的一个实例。这个接口定义了一个简单的Java对象和JMS消息之间进行转换的约定。它的默认实现SimpleMessageConverter支持在StringTextMessagebyte[]BytesMesssagejava.util.MapMapMessage之间进行转换。通过使用转换器,你的应用代码可以专注于通过JMS发送或接收的业务对象,并不用为了怎样将它描述为一个JMS消息而费心。

沙箱目前包含MapMessageConverter,它使用反射在JavaBean和MapMessage之间进行转换。你还可以选择使用XML组包的转换器,如JAXB、Castor、XMLBeans或Xstream,来创建一个TextMessage来描述该对象。

消息属性、消息头和消息体的设置,一般不能被封装在一个转换器类中,为了调整它们,接口MessagePostProcessor可以使你在消息转换后,发送前,访问消息。下面的例子展示了如何在一个java.util.Map被转换为消息之后修改一个消息的头和属性。

public void sendWithConversion() {
    Map m = new HashMap();
    m.put("Name", "Mark");
    m.put("Age", new Integer(35));
    jt.convertAndSend("testQueue", m, new MessagePostProcessor() {

         public Message postProcessMessage(Message message)
            throws JMSException {
            message.setIntProperty("AccountID", 1234);
            message.setJMSCorrelationID("123-00001");

            return message;
        }
    });
}
      

这是一个由上面得到的消息

MapMessage={ 
  Header={ 
    ... standard headers ...
    CorrelationID={123-00001} 
  } 
  Properties={ 
    AccountID={Integer:1234}
  } 
  Fields={ 
    Name={String:Mark} 
    Age={Integer:35} 
  } 
}
      

14.4.4. SessionCallback和ProducerCallback

虽然发送操作涵盖了很多普通的使用场景,但是有些情况你需要在JMS Session或MessageProducer上执行多个操作。SessionCallbackProduerCallback分别暴露了JMS Session和Session/MessageProducer对。JmsTemplate的execute()方法会执行这些接口上的回调方法。

 

 

=====================================================================================

  

jms事务aop配置

<!-- jms 事务管理 -->
    
<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
        
<property name="connectionFactory" ref="jmsQueueConnectionFactory"></property>
    
</bean>
    
<bean id="jmsTransInterceptor" class="web.common.JMSTransInterceptor">
        
<property name="jmsTransactionManager" ref="jmsTransactionManager"></property>
    
</bean>
    
<bean id="jmsTransAdvisor" 
        class
="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        
<property name="advice">
            
<ref local="jmsTransInterceptor"/>
        
</property>
        
<property name="patterns">
            
<list>
                
<value>send*</value>
            
</list>
        
</property>
    
</bean>    
    
<bean id="jmsTransTemplate" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean">

        
<property name="interceptorNames">
            
<list>
                
<value>jmsTransAdvisor</value>
            
</list>
        
</property>
    
</bean>

interceptor

 

import org.aopalliance.intercept.MethodInterceptor;
import
 org.aopalliance.intercept.MethodInvocation;
import
 org.springframework.transaction.PlatformTransactionManager;
import
 org.springframework.transaction.TransactionStatus;
import
 org.springframework.transaction.support.DefaultTransactionDefinition;

public class JMSTransInterceptor implements MethodInterceptor...
{
    
private
 PlatformTransactionManager jmsTransactionManager;    
    
    
public PlatformTransactionManager getJmsTransactionManager() ...
{
        
return
 jmsTransactionManager;
    }

    
public void setJmsTransactionManager(
            PlatformTransactionManager jmsTransactionManager) 
...
{
        
this.jmsTransactionManager =
 jmsTransactionManager;
    }


    
public Object invoke(MethodInvocation invocation) throws Throwable ...{
        Object result
=null
;
        
try...
{
            TransactionStatus ts
=jmsTransactionManager.getTransaction(new
 DefaultTransactionDefinition());
            result
=
invocation.proceed();
            jmsTransactionManager.commit(ts);
        }
catch (Exception e) ...{
            e.printStackTrace();
        }

        
return result;
    }

}

分享到:
评论

相关推荐

    jms-1.1.jar(jms工具jar包)

    10. **消息类型**:JMS支持多种消息类型,包括文本消息、对象消息、映射消息、流消息和二进制消息,以适应不同的应用场景。 在实际应用中,`javax.jms-1.1.jar` 提供了JMS API的实现,开发人员可以使用这些API创建...

    javax.jms-1.1.jar

    2. **消息模型**:JMS支持两种消息模型——点对点(Point-to-Point, PTP)和发布/订阅(Publish/Subscribe, Pub/Sub)。在点对点模型中,消息从一个队列(Queue)中发送到另一个队列,每个消息仅被一个消费者接收。...

    JMS 规范(英文)

    1. **消息模型**:JMS支持两种主要的消息模型——点对点(Point-to-Point,P2P)和发布/订阅(Publish/Subscribe,Pub/Sub)。在P2P模型中,消息被发送到一个队列,由消费者从队列中获取消息;而Pub/Sub模型下,消息...

    javax.jms包,sun的JMS接口规范包

    2. **消息模型**:JMS支持两种消息传递模型:点对点(Point-to-Point,P2P)和发布/订阅(Publish/Subscribe,Pub/Sub)。在P2P模型中,每个消息仅由一个消费者接收,通常通过队列实现;在Pub/Sub模型中,消息可以被...

    JMS消息模型 JMS学习.doc

    - **可靠性**:JMS支持事务处理,确保消息的可靠传递,即使在系统故障后也能恢复未完成的事务。 - **扩展性**:随着系统规模的增长,JMS能够轻松添加更多的消息消费者,以处理更多的消息负载。 总的来说,JMS是一个...

    JMS入门小例子以及weblogic安装,并且在weblogic中配置JMS服务

    5. **配置应用程序**:在应用中引入JMS相关的依赖库,如JMS API、Spring框架的JMS支持和其他必要的库(如WebLogic客户端库)。 6. **编写接收端和发送端代码**:接收端通过监听器等待消息,发送端则负责创建消息并...

    JMS demo 及 资料

    6. **事务处理**: JMS支持两种类型的事务:JMS事务和X/Open分布式事务处理(X/Open DTP)。JMS事务适用于单个JMS提供者的环境,而X/Open DTP则用于跨多个JMS提供者的事务一致性。 7. **持久化与非持久化消息**: JMS...

    jms-1.1.jar

    JMS支持两种主要的消息模型:点对点(Point-to-Point,P2P)和发布/订阅(Publish/Subscribe)。 点对点模型中,消息由一个生产者发送到一个队列,然后由一个或多个消费者接收,但每个消息只能被一个消费者消费。...

    JMS规范教程pdf

    JMS支持两种主要的消息传递模式: - **点对点(Point-to-Point)**:在此模式下,每个消息被发送到一个队列,每个消息只能被一个消费者接收。一旦被一个消费者接收,消息就会从队列中移除。 - **发布/订阅...

    JMS 中文 规范

    - **消息风格:** JMS支持两种主要的消息风格:点对点(每个消息只有一个消费者)和发布/订阅(消息被广播到多个订阅者)。 - **JMS接口:** JMS提供了一系列接口,如`javax.jms.Connection`、`javax.jms.Session`...

    JMS1.1规范(中文)

    10. **消息类型**:JMS支持多种消息类型,包括TextMessage(文本消息)、ObjectMessage(序列化Java对象)、BytesMessage(二进制数据)、MapMessage(键值对形式的数据)和StreamMessage(流式数据)。 11. **事务...

    SpringJMS示例代码

    SpringJMS支持两种消息模型:点对点(Queue)和发布/订阅(Topic)。点对点模型中,每个消息仅由一个消费者接收;而在发布/订阅模型中,消息可以被多个订阅者接收。 7. **消息持久化** SpringJMS和ActiveMQ结合,...

    JMS中间件ActiveMQ介绍

    - **消息模型**:JMS 支持两种主要的消息模型 —— 点对点(Point-to-Point, PTP)和发布/订阅(Publish/Subscribe, Pub/Sub)。 - **可靠消息传输**:确保消息能够准确无误地送达目标。 - **事务支持**:提供了...

    JBOSS建立JMS应用实例

    2. 消息模型:JMS支持两种消息模型——点对点(Point-to-Point)和发布/订阅(Publish/Subscribe)。前者基于队列,后者基于主题。 3. JMS实体:主要包括Message(消息)、MessageProducer(消息生产者)、...

    JMS specification

    3. **消息类型**:JMS支持多种类型的消息,包括文本消息、映射消息、流消息等。 4. **事务支持**:为了确保数据完整性,JMS提供了事务处理的支持。 5. **安全性**:JMS支持身份验证和授权机制,可以实现安全通信。 ...

    jboss-jms包

    - **消息模型**:JMS支持两种消息模型,点对点(Point-to-Point,P2P)和发布/订阅(Publish/Subscribe,Pub/Sub)。 - P2P模型中,消息从一个生产者发送到一个队列,然后由一个或多个消费者消费。消息一旦被消费...

    jms.rar_jar j_java jms_jms_jms jar_jms.j

    2. **消息模型**:JMS支持两种消息模型——点对点(Point-to-Point, PTP)和发布/订阅(Publish/Subscribe)。PTP模型中,每个消息只有一个消费者,常用于事务处理;发布/订阅模型中,一个消息可以被多个消费者...

    JMS完全实例(八个实例)

    JMS支持两种消息监听模式:同步和异步。同步监听通常通过调用MessageConsumer的receive方法实现,而异步监听则通过实现MessageListener接口来完成。实例中可能会展示如何创建消息监听器,并在接收到消息时执行特定...

    Sun 官方JMS教程

    - **事务处理**:JMS支持本地事务和全局事务,确保消息处理的原子性和一致性。 - **持久化**:消息可以被持久化存储,以防止系统崩溃时消息丢失。 #### 七、结语 JMS作为Sun Microsystems推出的官方消息中间件标准...

    JMS中/英文帮助文档

    5. **主题(Topic)与队列(Queue)**:JMS支持两种消息模式——发布/订阅(Publish/Subscribe)和点对点(Point-to-Point)。主题适用于广播式通信,多个消费者可以订阅同一个主题并接收消息。队列则遵循一对一的...

Global site tag (gtag.js) - Google Analytics