JMS Connection是一个客户端到JMS提供商间的活动连接。它通常分配在Java虚拟机外部的提供商的资源。

Connection对象支持并发使用。

Connection用作几个目的:

• 它封装了一个与JMS提供商的连接。他通常代表一个在提供商服务域和客户端间的打开的TCP/IP Socket。

• 在客户端授权时创建它。

• 它可以指定一个唯一的客户端标识。

• 它创建Session对象。

• 它提供ConnectionMetaData。

• 它支持可选的ExceptionListener。

由于在创建Connection时设置授权和通讯,因此Connection相对是重量级的JMS对象。大多数客户端使用一个连接来执行所有的消息动作。其他更先进的应用可以使用多个Connection。JMS使用多个连接不是架构方面的原因(除了当客户端作为两个不同提供商间的网关时);但是可能有操作方面的原因。

4.3.1 授权

当创建连接时,客户端可以指定它的信任状如用户名/密码。

如果没有指定信任状,那么使用当前线程的信任状。这一点上,JDK没有定义线程缺省信任状的概念。但是在不久的将来可能会定义。目前,可以使用JMS客户端运行使用的用户标识。

4.3.2 客户端标识

设置客户端标识的最好方式是将它配置在一个客户端特有的ConnectionFactory中,然后透明的将它赋给它创建的连接。另一个方法就是客户端可以用提供商特有的值来设置连接的客户端标识。显式地设置连接的客户端标识的工具不是一个用于覆盖已经被配置的标识的机制。它只是用于管理员没有配置标识的情况。如果标识已经存在,那么企图更改它必须抛出IllegalStateException。

如果客户端显式地设置标识,那么它必须在创建连接后和在连接上发生其他动作之前立即设置。如果在这个时刻后再设置,则设置客户端标识就是程序性错误,将抛出IllegalStateException。

客户端标识的目的是将连接和它的对象与由提供商按客户端维护的状态关联起来。

按照定义,被客户端标识标识的客户端状态在一个时刻只能由一个客户端“在用”。JMS提供商必须防止并发执行的客户端来使用它。阻止方式可以是当企图这样使用时抛出各种JMSException的形式;也可以阻塞后续的客户端;或者是其他的解决方案。JMS提供商必须保证这种共享单个客户端状态的企图不能引起消息的丢失或重复处理。

由JMS标识的唯一的单个客户端状态要支持长期订阅。

4.3.3 Connection设置

JMS客户端通常创建一个Connection,一个或多个Session和大量的MessageProducer和MessageConsumer。当Connection被创建时,它处于stopped模式。意思是没有消息可以转发给它。

通常会让昂Connection处于停止模式直到设置完成。设置完成后调用Connection.start()方法,且消息开始到达Connection的消费者。这种设置约定减小了客户端还在设置它自己时就有异步消息转发的问题。

Connection可以立即启动然后再进行设置。这样,客户端必须做好它们在设置过程中处理异步消息转发的准备。

MessageProducer可以在Connection是停止时发送消息。

要注意,客户端必须在连接启动后它才能转发消息。JMS提供商必须保证这种情况。

4.3.4 中止消息的转发

连接对接收到的消息的转发可以使用stop()方法被临时停止。可以使用start()方法重新启动它。当连接被停止时,禁止向所有连接的MessageConsumer进行转发:

同步接收被阻塞,消息不被转发到MessageListener。

停止连接对发送消息没有影响。停止一个已经停止的连接和启动一个已经启动的连接被忽略。

在消息的转发被停止后才能返回stop方法。这意味着停止后,不会调用任何消息监听器,并且所有的等待接收消息的控制线程在连接重新启动前不会返回消息。用于已停止连接的的接收计时器仍然有效,因此接收可能会超时并返回一个空消息。

如果stop方法被调用时消息监听器(MessageListener)仍在运行,则必须在所有的监听器都返回后才能停止。当这些消息监听器将要完成时,他们必须拥有连接的所有服务。

4.3.5 关闭Connection

由于提供商通常为Connection分配JVM外部的资源,因此客户端应当在它们不需要的时候关闭这些资源。依赖垃圾回收来回收这些资源可能不是非常及时。

关闭操作将终止所有连接会话消费者接收的未处理消息。接收可能返回一个消息也可能返回null,这要根据关闭时刻是否可以获得一个消息。

注意,在这种情况下,如果消息消费者企图用这个关闭的连接来处理最后的消息,它很可能会得到一个异常。开发者在写消息消费者的时候必须考虑这种“最后的消息”。必须再次强调,消息消费者不能依靠空返回值来判断“最后的消息”。

如果一个或多个消息监听器在连接关闭被调用时正在处理消息,那么在控制没有返回给JMS提供商之前就必须保持连接和会话的所有功能都可以被那些监听器获得。

当连接被关闭时,直到消息处理按顺序都被停止后关闭方法才能返回。这意味着所有正在运行的消息监听器已经返回且所有未处理的接收已经返回。

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

关闭连接必须回滚处于处理的交易会话中的事务(注:术语“交易会话”指的是会话的提交和回滚方法用于分割会话的本地事务。在这种情况下会话的工作和外部的事务管理器的 工作是一致的,此时不使用会话的提交和回滚方法,被关闭的会话的工作的结果随后由事务管理器决定。)。关闭连接不会强迫客户端确认会话的确认。调用来自已关闭的会话的已接收消息的acknowledge方法必须抛出IllegalStateException。对于那些要求由JMS客户端连续可靠处理的队列和长期订阅来说,这些语义保证关闭连接不会造成消息的丢失。

一旦连接被关闭,企图使用它或它的会话或它们的消息消费者和生产者必须抛出IllegalStateException(必须忽略对这些对象的close方法的调用)。但继续使用通过这个连接创建或接收的消息对象仍是有效的,除了已接收消息的acknowledge方法。

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

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不是用于监听由连接抛出的所有异常)。