友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
富士康小说网 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

JMS简明教程(PDF格式)-第7部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!



   如果stop 方法被调用时消息监听器(MessageListener)仍在运行,则必须在所有的监听器 

都返回后才能停止。当这些消息监听器将要完成时,他们必须拥有连接的所有服务。  



4。3。5 关闭Connection  



   由于提供商通常为Connection 分配JVM 外部的资源,因此客户端应当在它们不需要的 

时候关闭这些资源。依赖垃圾回收来回收这些资源可能不是非常及时。  

   关闭操作将终止所有连接会话消费者接收的未处理消息。接收可能返回一个消息也可能 

返回null,这要根据关闭时刻是否可以获得一个消息。  

   注意,在这种情况下,如果消息消费者企图用这个关闭的连接来处理最后的消息,它很 

可能会得到一个异常。开发者在写消息消费者的时候必须考虑这种“最后的消息”。必须再 

次强调,消息消费者不能依靠空返回值来判断“最后的消息”。  

   如果一个或多个消息监听器在连接关闭被调用时正在处理消息,那么在控制没有返回给 

JMS 提供商之前就必须保持连接和会话的所有功能都可以被那些监听器获得。  

   当连接被关闭时,直到消息处理按顺序都被停止后关闭方法才能返回。这意味着所有正 

在运行的消息监听器已经返回且所有未处理的接收已经返回。  

   如果连接被关闭,不需要关闭它的组成对象。连接关闭足以通知 JMS                 提供商应当释放 

连接的所有资源。  

   关闭连接必须回滚处于处理的交易会话中的事务(注:术语“交易会话”指的是会话的 

提交和回滚方法用于分割会话的本地事务。在这种情况下会话的工作和外部的事务管理器的 

工作是一致的,此时不使用会话的提交和回滚方法,被关闭的会话的工作的结果随后由事务 

管理器决定。)。关闭连接不会强迫客户端确认会话的确认。调用来自已关闭的会话的已接收 

消息的acknowledge 方法必须抛出IllegalStateException。对于那些要求由JMS 客户端连续可 

靠处理的队列和长期订阅来说,这些语义保证关闭连接不会造成消息的丢失。  

   一旦连接被关闭,企图使用它或它的会话或它们的消息消费者和生产者必须抛出 

IllegalStateException  (必须忽略对这些对象的close 方法的调用)。但继续使用通过这个连接 

创建或接收的消息对象仍是有效的,除了已接收消息的acknowledge 方法。  

   关闭一个已关闭的连接不必抛出异常。  



                                                            33 / 66  

  


…………………………………………………………Page 34……………………………………………………………

                                       



4。3。6 会话(Session)  



    Connection 是Session 的工厂,它底层使用对JMS 提供商的连接来生产和消费消息。  



4。3。7 ConnectionMetaData  



    Connection 提供ConnectionMetaData 对象。这个对象提供了提供商支持的JMS  的最新 

版本和提供商的产品名和版本。  

    它也提供了连接支持的JMS 定义的属性名列表。  



4。3。8 ExceptionListener  



    如果JMS 提供商检测到与连接有关的问题,那么它将通知连接的ExceptionListener,如 

果它已经被注册。为了取出ExceptionListener,JMS 提供商调用连接的getExceptionListener() 

方法。这个方法返回这个连接的ExceptionListener。如果没有注册ExceptionListener,则返回 

null 。连接然后可以通过调用监听器的 onException()方法来使用监听器,传入描述问题的 

JMSException 。  

    这可以让客户端异步通知问题。某些连接只消费消息,因此它们没有其他途径来获知它 

们的连接已经失败。  

    连接序列化ExceptionListener 的执行。  

    JMS 提供商应当在通知客户端之前尽力解决连接问题。  

    转发到ExceptionListener 的异常是那些没有其他地方可报告的异常。如果在JMS 调用连 

接时抛出异常,按照定义不会将这个异常转发给 ExceptionListener                       (换句话说, 

ExceptionListener 不是用于监听由连接抛出的所有异常)。  



4。4  Session  



    JMS Session  是一个单线程的上下文(对能够使用会话对象或它创建的线程的数量没有 

限制。限制是会话的资源不应当被多个线程并发使用。这由用户来保证满足这个限制。最简 

单的方式是使用一个线程。在异步转发的情况下,使用一个线程来设置停止模式然后启动异 

步转发。在更复杂的情况下,用户必须提供显式的同步。),用于生产和消费消息。尽管会话 

可以给提供商分配JVM 外部的资源,但是它被看作是轻量JMS 对象。  

    Seesion 用于几个目的:  

    z   它是MessageProducer 和MessageConsumer 的工厂。  

    z   它是TemporaryTopic 和TemporaryQueue 的工厂。  

    z   它为需要动态操纵提供商专有目的地名字的客户端提供了一种创建Queue 或Topic 

        对象的途径。  

    z   它提供了提供商优化后的消息工厂。  

    z   它支持事务串,这些事务将跨会话生产者和消费者的工作组合成原子单元。  

    z   它为它消费的消息和它生产的消息定义了一个连续的顺序。  

    z   它保留它消费的消息直到这些消息被确认。  



                                                                      34 / 66  

  


…………………………………………………………Page 35……………………………………………………………

                                    



    z  它序列化注册到它的MessageListener 的执行。  

    z  它是QueueBrowser 的工厂。  



4。4。1 关闭会话  



    由于提供商可以代表会话分配位于JVM  之外的资源,客户端应当在这些资源不需要的 

时候关闭它们。依靠垃圾回收来最终回收它们不是非常及时的。对于由会话创建的 

MessageProducer 和MessageConsumer 来说同样需要这样做。  

    关闭会话会中止这个会话上的所有消息处理。它必须处理由会话消费者未处理的接收或 

正在运行的消息监听器的关闭,正如在节4。3。5  “关闭连接”中所述。  

    关闭会话的方法可以从一个不同于当前控制这个会话的控制线程调用。  

    当会话关闭被调用时,在消息处理被按顺序停止前关闭方法不能返回。这意味着不会有 

消息监听器正在运行,且如果有未处理的接收,则它返回null 或者一个消息。  

    当会话被关闭时,不需要关闭它的消息生产者和消费者。会话关闭足够通知 JMS                        提供 

商释放会话的所有资源。  

    关闭有事务的会话必须回滚处理中的事务。关闭客户端确认的会话不强迫确认。  

    一旦会话被关闭,那么企图使用它或它的消费者和生产者必须跑出IllegalStateException 

 (必须忽略对这些对象close  方法的调用)。继续使用通过这个会话创建或接收的消息对象 

是有效的,除了已接收消息的acknoledge 方法。  

    关闭一个已关闭的会话不能抛出异常。  



4。4。2 创建MessageProducer 和MessageConsumer  



    会话可以创建和服务于多个 MessageProducer         和 MessageConsumer 。参见节 4。5 

 “MessageConsumer”和节4。6  “MessageProducer”了解创建和使用它们的详细信息。  

    尽管会话可以创建多个生产者和消费者,它们必须依次使用。在效果上,只有一个逻辑 

控制线程可以使用它们。这在后面会详细的解释。  



4。4。3 创建临时目的地  



    尽管会话被用于创建临时目的地,这只是为了方便。它们的范围实际上是整个连接。它 

们的生命周期与连接相同,连接的所有会话都可以创建临时目的地的MessageConsumer。  

    临时目的地(TemporaryQueue  或TemporaryTopic 对象)是系统为连接生成的唯一的目 

的地。只有它们自己的连接才可以为它们创建MessageConsumer。  

    临时目的地的通常用法师作为JMSReplyTo 的目的地。  

    每个TemporaryQueue 或TemporaryTopic 对象都是唯一的。不能够被复制。  

    由于临时目的地可以分配JVM  外部的资源,如果这些资源不再使用,应当及时删除它 

们。当它们被垃圾回收或连接关闭时,这些资源将被自动删除。  



4。4。4 创建目的地对象  



    大多数的客户端都将使用Destination,Destination 是JMS  的受管理对象,通过JNDI 查 



                                                                 35 / 66  

  


…………………………………………………………Page 36……………………………………………………………

                                  



找它们。这是最方便的方法。  

   某些特殊的客户端可能需要动态操纵使用提供商特有的目的地名来创建Destination。会 

话为JMS 提供商提供了实现这个功能的提供商专用的方法。  



4。4。5 优化消息实现  



   会话提供使用提供商优化过的实现来创建消息的方法。这可以让提供商最小化处理消息 

的负荷。  

   会话必须能够发生所有的JMS 消息而不管它们如何被实现的。  



4。4。6 使用会话的约定  



   会话被设计成一个时间只能由一个线程使用。一个例外情况是在会话或它的连接依次关 

闭时可以多个线程使用。参见节4。3。5  “关闭连接”和节4。4。1  “关闭会话”了解更详细的信 

息。  

   一个典型的用法是让一个线程阻塞在同步的 MessageConsumer  上,直到有消息到达。 

这个线程然后使用一个或多个MessageProducer。  

   如果已经有一个客户端控制线程正在这个会话中等待接收消息,那么另一个客户端控制 

线程不能同步接收消息。  

   另一个典型的用法是让一个线程通过创建会话的生产者和一到多个异步消费者来设置 

会话。在这种情况下,消息生产者不能独占消费者消息监听器。由于会话按顺序执行消费者 

的MessageListener,因此这些监听器可以安全地共享会话的资源。  

   如果在会话正在被设置时连接处于停止模式,那么客户端在完全准备好处理消息之前不 

需要处理到达的消息。这是最好的策略,因为它降低了设置和消息处理间出现冲突的可能性。 

当连接正在接收消息时可以创建和设置会话。在这种情况下,要注意保证会话的 

MessageProducer、MessageConsumer 和MessageListener 要按正确的顺序创建。例如,错误 

的顺序可能引起 MessageListener    使用还没有创建号的 MessageProducer ;或由于 

MessageListener 注册的顺序不正确而使得消息按错误的顺序到达。  

   如果客户端希望在其他线程消费消息时有一个线程产生消息,那么客户端应当为生产消 

息的线程使用独立的会话。  

   一旦连接被启动,则它的所有带有消息监听器的会话都致力于给它们转发消息的控制线 

程。从另外一个控制线程中使用这些会话的客户端代码是错误的。唯一的例外是这种非那个 

是可以用于会话或连接的关闭方法。  

   对会话增加单线程控制的限制的结果是带消息监听器的会话也不能同步接收消息。会话 

要么致力于用作转发消息到消息监听器的控制线程,要么致力于由客户端初始化的控制线程。 

不能在同一个会话中同时使用。  

   另一个结果是,连接必须在停止模式下对带多个消息监听器的会话进行设置。原因是当 

连接正在转发消息,一旦第一个消息监听器被注册,则会话就由向这个监听器转发消息的控 

制线程控制。此时,客户端的控制线程不能进一步配置这个会话。  

   对大多数客户端来说,将它们的工作分派到多个会话是很正常的。这个模型可以让客户 

端简单的启动和随着并发增长的需要而逐渐地增加消息处理。  



                                                             36 / 66  

  


…………………………………………………………Page 37……………………………………………………………

                                     



4。4。7 事务  



    Session 可选地可以被指定为事务性的。每个事务性的会话支持单序列的事务。每个事 

务将一系列生成的消息和一系列消费的消息分组到一个原子工作单元。效果是,事务将会话 

的输入消息流和输出消息流组织称一系列的原子单元。当事务提交时,输入原子单元被确认, 

输出原子单元被发送。如果事务回滚,则它生产的消息被销毁,它消费的消息被自动恢复。 

关于会话恢复的详细信息,参见节4。4。11  “消息确认”。  

    会话使用它的mit()或rollback()方法来完成会话。当前事务完成时会自动启动下一个 

事务。因此,事务性的会话当前总会有一个事务。  

   JTS 或一些其他的事务监控器工具可以被用于将会话的事务和其它资源(数据库,其他 

的JMS 会话等等)上的事务组合在一起。由于Java 分布式事务由JTA 事务分割API 控制,因 

此在这种上下文中使用会话的 mit                    和 rollback 方法将抛出 JMS        的 

TransactionInProgressException 。  



4。4。8 分布式事务  



   JMS 不要求提供商支持分布式事务;但是如果提供商支持了,则应当通过JTA XAResource  

API 来提供分布式事务。  

   JMS 提供商也可以是分布式事务监听器。如果它是,那么它应当通过JTA API 提供事务 

控制。  

    尽管对JMS 客户端来说它可以直接处理分布式事务,但JMS 客户端尽量不要这样做。 

使用基于XA 接口的JMS 客户端在第8 章“JMS 应用服务器工具”中描述,但这种客户端不 

能跨不同的JMS  实现进行移植,因为这些接口是可选的。在JMS  中支持JTA  是为了系统提 

供商能够将JMS 集成到他们的应用服务器产品中。参见第8 章“JMS 应用服务器工具”了解 

更详细的信息。  



4。4。9 多会话  



    一个客户端可以创建多个会话。每个会话都是一个独立的消息生产者和消费者。  

    对于Pub/Sub,如果两个回合都有一个TopicSubscriber ,且都订阅同一个Topic ,那么每 

个订阅者都会收到消息。它们之间不会相互阻塞。  

    对于PTP,JMS 没有指定对同一个Queue 并发QueueReceiver 的语义。但是,JMS 没有 

禁止提供商提供这个功能。因此,向多个QueueReceiver 转发消息将依赖JMS 提供商的实现。 

但这是不可移植的。  



4。4。10 消息排序  



   JMS 客户端不需要理解它们什么时候可以依靠消息排序,什么时候不能。  



                                                                 37 / 66  

  


…………………………………………………………Page 38……………………………………………………………

                                   



4。4。10。1  消息接收的顺序  



    由会话消费的消息定义了一系列的顺序。这个顺序是重要的,因为它定义了消息确认的 

顺序。参见4。4。11  “消息确认”了解详细信息。每个会话消费者交叉读取会话输入消息流中 

的消息。  

   JMS 定义了由会话发送到目的地的消息必须按它们发送的顺序被接收(参见节4。4。10。2 

 “消息发送的顺序”了解限制条件)。这节定义了一部分在会话输入消息流上排序的约束。  

   JMS 没有定义跨目的地接收消息的顺序或从多个会话发送的跨目的地的消息的顺序。会 

话输入消息流的顺序依赖于时间。不在应用的控制之下。  



4。4。10。2  消息发送的顺序  



   尽管客户端松散地查看在会话中生产的消息,这些消息形成了一个有序的发送消息流, 

对流进行整体排序是没有意义的。对接收客户端唯一可见的排序是会话发送到一个特定目的 

地的消息的顺序。有几个事情可以影响整个顺序:  

   z   高优先级的消息可以跳到低优先级消息的前面。  

   z   客户端可以不接收NON_PERSISTENT 的消息,因为JMS 提供商失败造成。  

   z   如果 PERSISTENT 和 NON_PERSISTENT 消息被发送到一个目的地,那么只在转发模 

       式中保证顺序。也就是说,稍晚的NON_PERSISTENT 消息可以在稍早的PERSISTENT 

       之间到达;但是不会在稍早的同优先级的NON_PERSISTENT 消息之前到达。  

   z   客户端使用事务性的会话将会话发送的消息分组到原子单元(一个 JMS  事务的生 

       产者组件)。发送到特定目的地的消息的事务顺序是有意义的。跨目的地发送的消 

       息的顺序是没有意义的。参见4。4。7  “事务”了解更详细的信息。  



4。4。11 消息确认  



   如果会话是事务性的,那么消息确认自动由mit 处理,且恢复自动由rollback 处理。  

   如果会话不是事务性的,有三个确认选择,且手工处理恢复:  

   z   DUPS_OK_ACKNOWLEDGE——这个选项告诉会话懒惰确认消息的传递。如果 JMS 

       失败,这很可能造成传递重复消息,因此这个选项只用于可以忍受重复消息的消费 

       者。它的好处是减少了会话为防止重复所要做的工作。  

   z   AUTO_ ACKNOWLEDGE——使用这个选项,当消息被成功地从调用接收返回或处理 

       消息的MessageListener 成功返回时,会话自动确认客户端的消息接收。  

   z   CLIENT_ ACKNOWLEDGE——使用这个选项,客户端通过调用消息的acknowledge 方 

       法来确认消息。确认一个被消费的消息会自动确认被该会话转发的所有消息。  

   当使用CLIENT_ ACKNOWLEDGE 模式时,客户端可以在处理它们时产生大量未确认消息。 

JMS 提供商应当为管理员提供限制客户端超量运行的途径,以便客户端不会造成资源耗尽并 

保证当它们使用的资源被临时阻塞时造成失败。  

   会话的recover 方法用于停止一个会话然后使用第一个未确认消息来重新启动它。事实 

上,会话的被转发消息序列被重新设置到最后一个确认消息之后。现在转发的消息序列可以 

与起初转发的消息序列不同,因为消息到期和收到更高优先级的消息。  

   会话必须设置消息的redelivered 标记,表示它是由于恢复而被重新转发的。  



                                                             38 / 66  

  


…………………………………………………………Page 39……………………………………………………………

                                   



4。4。12 消息的重复转发  



   JMS 提供商不能重复转发已确认消息。  

    当客户端使用AUTO_ACKNOWLEDGE 模式时,它不会直接控制消息的确认。由于这种客 

户端不能确切知道某个消息是否已经被确认,因此它们必须做好再次收到最后消费的消息的 

准备。这可能由于客户端完成它的工作恰好在防止消息确认发生失败之前引起。只有会话测 

最后消费的消息会遇到这种情况。JMSRedelivered 消息头字段将用于这种情况下被重发的消 

息。  



4。4。13 消息的重复产生  



   JMS 提供商不能生产重复的消息。这意味着生产消息的客户端可以依赖JMS 提供商来保 

证消息的消费者一个消息只会接收一次。客户端的错误不会引起提供商重复一个消息。  

   如果在客户端提交和提交方法返回期间出现错误,那么客户端不能决定事务是否被提交 

还是被回滚。当非事务性的发送一个 PERSISTENT 消息和发送方法返回之间产生错误时,会 

产生同样的不确定性问题。  

   这种不确定性由
返回目录 上一页 下一页 回到顶部 9 9
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!