JMS 消息传递域

在 JMS API 出现之前,大多数消息传递产品支持点对点或者发布/订阅消息传递方法。
JMS 为每种方法提供了一个单独的域,并定义了每个域的合规性。
任何 JMS 提供者都可以实现两个域或者一个域,这是他自己的选择。
JMS 提供了通用接口,使我们能够以不特定于任一域的方式使用 JMS API。

让我们更详细地查看这两种类型的消息传递域,以了解 JMS 的工作原理。

点对点消息传递域

在点对点消息传递域中,应用程序建立在消息队列、发送方和接收方的基础上。
每条消息都被寻址到一个特定的队列。

队列保留发送给它们的所有消息,直到消息被消耗或者过期。
PTP 消息传递有一些特点:

  • 每条消息只有一个客户端。
  • 消息的发送方和接收方没有时间依赖性。
  • 接收方可以在发送方发送消息时获取消息,无论消息是否正在运行。
  • 接收方收到消息后发送确认。

发布/订阅消息传递域

在发布/订阅消息域中,只发布一条消息,通过充当公告板的 Topic 传递给所有客户端。

发布者和订阅者一般都是匿名的,可以动态发布或者订阅主题。
Topic 负责保存和传递消息。
只要需要分发给当前客户端,主题就会保留消息。

其中一些特征是:

  • 一条消息可以有多个订阅者。
  • 发布者和订阅者具有时间依赖性。订阅主题的客户端只能消费在客户端创建订阅后发布的消息,并且订阅者必须继续处于活动状态才能消费消息。

JMS 的优点

  • 默认情况下,异步JMS 是异步的。所以要接收消息,客户端不需要发送请求。当消息可用时,消息将自动到达客户端。
  • 可靠的
    JMS 提供了保证消息将只传递一次的工具。我们知道重复的消息会产生问题。JMS 可避免此类问题。
https://onitroad.com 更多教程

JMS 参与对象

JMS 应用程序有一些基本的构建块,它们是:

  • 受管理对象 - 连接工厂和目的地
  • 连接
  • 会话
  • 消息生产者
  • 消息消费者
  • 消息监听器

JMS 管理对象

JMS 应用程序提供两种类型的受管对象:

  • 连接工厂 (Connection Factory)
  • 目的地 (Destination)

这两个管理对象是由 JMS 系统管理员在 JMS Provider 中使用应用程序服务器的管理控制台创建的。
这两个对象都存储在应用程序服务器 JNDI 目录或者 JNDI 注册表中。

连接工厂

客户端使用一个对象,该对象是用于创建到提供者的连接的连接工厂。

它在 JMS 提供程序和 JMS 客户端之间创建连接。
当 JMS 客户端(例如发送方或者接收方)在 JNDI 注册表中搜索此对象时,JMS 客户端会收到一个连接对象,该对象不仅仅是 JMS 提供程序和 JMS 客户端之间的物理连接。
使用此连接,客户端可以与目标对象进行通信,以将消息发送或者接收到队列或者主题中。
让我们通过一个例子来理解它发送消息:

QueueConnectionFactory queueConnFactory = (QueueConnectionFactory) initialCtx.lookup ("primaryQCF");
Queue purchaseQueue = (Queue) initialCtx.lookup ("Purchase_Queue");
Queue returnQueue = (Queue) initialCtx.lookup ("Return_Queue");

目的地

客户端使用一个称为目的地的对象,用于指定它产生的消息的目标和使用它的消息源。
JMS 应用程序使用两种类型的目标队列或者主题。
该代码指定队列和主题。

创建队列会话

QueueSession ses = con.createQueueSession (false, Session.AUTO_ACKNOWLEDGE);  //get the Queue object  
Queue t = (Queue) ctx.lookup ("myQueue");  //create QueueReceiver  
QueueReceiver receiver = ses.createReceiver(t);

创建主题会话

TopicSession ses = con.createTopicSession (false, Session.AUTO_ACKNOWLEDGE); // get the Topic object  
Topic t = (Topic) ctx.lookup ("myTopic");  //create TopicSubscriber  
TopicSubscriber receiver = ses.createSubscriber(t);

为什么需要JMS

在 Java 中,如果一个人想要将消息从一个应用程序发送到另一个应用程序,这样两个应用程序都不知道彼此的任何信息,即使它们可能部署在完全没有依赖关系的不同大陆。
例如,一个应用程序 A 在荷兰运行,另一个应用程序在美国运行,并且 B 有兴趣在 A 上发生独特的事情时从 A 获取一些更新/消息。
可能有 N 个这样的应用程序对这样的应用程序感兴趣来自 A 的更新

在这种情况下,java 以 JMS 的形式提供了它的最佳解决方案,并解决了上面讨论的完全相同的问题。

当我们编写任何基于事件的应用程序时,JMS 也很有用,比如聊天服务器,它需要一个发布事件机制来在服务器之间向与服务器连接的客户端发送消息。
由于 JMS 与 RMI 不同,因此在从客户端向服务器发送消息时不需要目标对象在线可用。
服务器发布消息并忘记它,每当客户端上线时,它都会获取消息。
对于当今世界上非常常见的问题,它是非常强大的解决方案。

消息消费

在 JMS 中,消息消费可以通过两种方式完成:

同步

在同步消息消费中,订阅者/接收者通过调用“receive()”方法从目的地请求消息。
receive()方法中将阻塞直到消息到达或者如果消息没有在给定时间内到达则超时。
就像带有一些返回值的普通 java 方法调用一样。

异步

在异步消息消费中,订阅者可以向消费者注册(或者订阅)为消息侦听器。
消息侦听器与事件侦听器相同,每当消息到达目的地时,JMS 提供者将通过调用侦听器的 onMessage() 方法传递消息,该方法将对消息的内容进行操作。

JMS 连接

该连接封装了与 JMS 提供者的虚拟连接。
连接实现了 Connection 接口,当它有一个 ConnectionFactory 对象时,我们就可以使用它来创建一个连接。

Connection connection = connectionFactory.createConnection();

创建任何连接后,应在应用程序完成之前关闭它们:

connection.close();

JMS 会话

会话是一个单线程上下文,用于生成和消费消息。

会话用于创建以下内容:

  • 消息生产者
  • 消息消费者

session 实现了 Session 接口,在创建了 Connection 对象之后,我们使用它来创建一个 Session。

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

JMS 消息生产者

消息生产者是一个由会话创建的对象,用于向目的地发送消息。
这实现了 MessageProducer接口。
我们使用 Session 为目标、队列或者主题对象创建一个 MessageProducer

MessageProducer producer = session.createProducer(dest);
MessageProducer producer = session.createProducer(queue);
MessageProducer producer = session.createProducer(topic);

创建消息生产者后,通过使用send方法发送消息。

producer.send(message);

JMS 消息消费者

消息消费者是一个由会话创建的对象,用于接收在目的地发送的消息。
它将实现MessageConsumer接口。
我们使用会话为目的地、队列或者主题对象创建 MessageConsumer。

MessageConsumer consumer = session.createConsumer(dest);
MessageConsumer consumer = session.createConsumer(queue);
MessageConsumer consumer = session.createConsumer(topic);

JMS 消息侦听器

消息侦听器是一个对象,它充当消息的异步事件处理程序。
消息侦听器实现了 MessageListener接口,其中包含一个方法 onMessage()
在这个方法中,我们定义了消息到达时要执行的操作。
通过使用setMessageListener(),我们使用特定的MessageConsumer定义消息侦听器。

Listener myListener = new Listener();
consumer.setMessageListener(myListener);

JMS 消息组件

JMS 客户端使用 JMS 消息在系统之间进行通信。
JMS 消息格式简单但高度灵活,允许创建与格式匹配的消息。
JMS 消息分为三个部分。
他们是:

  • 消息头( Message Header)
    JMS 消息头包含预定义字段的数量,这些字段包含客户端和提供者用来标识和发送消息的值。预定义的标头是:- JMSDestination- JMSDeliveryMode- JMSMessageID- JMSTimestamp- JMSCorrelationID- JMSReplyTo- JMSRedelivered- JMSType- JMSExpiration- JMSPriority
  • 消息属性(Message Properties)
    在消息属性中,我们可以为消息创建和设置属性。消息属性是由应用程序设置或者读取的自定义名称值对。消息属性对于支持过滤消息很有用。JMS API 提供了一些提供者可以支持的预定义属性。消息属性是可选的。
  • 消息体(Message Body)
    在消息体中,JMS API 定义了五种消息体格式,它们也称为消息类型,允许我们以多种不同的形式发送和接收数据,并提供与现有消息格式的兼容性。它基本上由从 JMS 发送方发送到接收方的实际消息组成。不同的消息类型是:
    文本消息:由 javax.jms.TextMessage 表示。它用于表示文本块。
    对象消息:由 javax.jms.ObjectMessage 表示。它用于表示一个java对象。
    字节消息:由 javax.jms.BytesMessage 表示。它用于表示二进制数据。
    流消息:由 javax.jms.StreamMessage 表示。它用于表示 Java 原始值列表。
    映射消息:由 javax.jms.MapMessage 表示。它用于表示一组关键字或者值对。
Java 消息服务(Message Service)

Java 消息服务(Java Message Service)是一种 API,它支持网络上计算机之间称为消息传递的正式通信。

它为标准消息协议和消息服务提供了一个通用接口,以支持 Java 程序。
它提供了创建、发送和阅读消息的工具。
JMS API 减少了程序员必须学习使用消息服务/产品的概念,它还提供支持消息应用程序的功能。

JMS 是一种在 J2EE 技术中用于应用程序以松散耦合方式与其他应用程序通信的技术。
这意味着必须进行通信的应用程序不是直接连接的,而是通过公共目的地连接的。

日期:2020-09-17 00:09:50 来源:oir作者:oir