JMS 入门学习

2 篇文章 0 订阅

前言

新公司现在的项目中有使用 ActiveMQ,所以在闲余时间自己也学习一下,浏览过很多文档及博客内容,发现入门容易,深入了解涉及也蛮多的。本文旨在记录一下如何入门,即使入门可能也会有疏漏,所以当做“抛砖引玉”,烦请各位多多指点。

介绍

JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持,类似于JDBC(Java Database Connectivity)。在实际应用中JMS+MQ服务器(即消息中间件)相结合来完成消息排队类型的应用程序开发。

MQ 服务器是什么?用 MQ 的说法,Message(消息)只是一个字节流(这个字节流可以是一个 XML 文档、一个序列化的 Java 对象、一个文本字符串或甚至是一条空消息),对消息的解释留给应用程序域来做,MQ 服务器不对消息施加任何语义和结构限制。消息存储在MQ服务器的消息队列中,MQ 服务器允许您使用JMS将消息加入到队列以及从队列中取走消息。

使用场景

消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。关于详细介绍可参考这篇关于消息队列的使用

JMS 消息传送对象和模式

为了发送或接收消息,JMS 客户端必须先连接到 JMS 提供者(该提供者通常作为消息代理实现):此连接在客户端与代理之间打开一个通信通道。接下来,客户端必须设置一个用来创建、生成和使用消息的会话。可以将该会话视为定义客户端与代理之间的特定对话的消息流。客户端本身就是消息生成方和/或消息使用方。消息生成方 向代理所管理的目的地发送一条消息。消息使用方访问该目的地以使用此消息。该消息包括消息头、属性(可选)和主体。消息主体用来保存数据;消息头中包含代理路由和管理消息所需的信息;属性可以由客户端应用程序或提供者定义,以满足处理消息的需要。
连接、会话、目的地、消息、生成方和使用方是构成 JMS 应用程序的基本对象。

通过这些基本对象,客户端应用程序可以使用两种消息传送模式(或域)发送和接收消息。

消息传送域

JMS API 定义通信的两种消息传送域:点对点消息传送发布/订阅消息传送

  1. 点对点消息传送

    在点对点域中,消息生成方被称为发送者,而使用方被称为接收者。它们通过被称为队列的目的地来交换消息:发送者生成队列中的消息;而接收者则使用队列中的消息。

    图示为点对点域中最简单的消息传送操作。
    说明:MyQueueSender 向队列目的地 MyQueue1 发送 Msg1。然后, MyQueueReceiver 从 MyQueue1 获得该消息。

    特点
    多个接收者可以使用一个队列中的多条消息,但每条消息只能由一个接收者使用。

    发送者和接收者之间不存在时间上的相关性:客户端发送一条消息后,无论接收者是否正在运行,都能获取该消息。

    消息在队列中按发送的顺序排列,但使用消息的顺序取决于多种因素,例如消息失效日期、消息优先级以及使用消息时是否使用了选择器。

    优势:
    由于多个接收者可以使用同一队列中的消息,因此如果消息的接收顺序不重要,则可以对消息的使用进行负载平衡。

  2. 发布/订阅消息传送

    在发布/订阅域中,消息生成方被称为发布者,而消息使用方则被称为订阅者。它们通过称为主题的目的地来交换消息:发布者生成主题中的消息;订阅者则订阅主题并使用主题中的消息。

    描述

    图示为发布/订阅域中的简单消息传送操作。
    说明:MyTopicPublisher 向目的地 MyTopic 发布 Msg1。然后,MyTopicSubscriber1 和 MyTopicSubscriber2 均从 MyTopic 接收 Msg1 的副本。

    特点
    多个订阅者可使用一个主题中的消息。订阅者可检索发布到一个主题中的所有消息,除非它们使用选择器过滤掉消息或消息在使用之前已过期。

    订阅者可共享连接或使用不同连接,但它们均可访问同一主题。

    长期订阅者可能处于活动状态,也可能处于非活动状态。在它们处于非活动状态时,代理会为它们保留消息。

    可在运行时动态添加和删除发布者和订阅者,这样,即可根据需要缩放消息传送系统。

    消息按发送的顺序发布到主题,但使用消息的顺序取决于多种因素,例如消息失效日期、消息优先级以及使用消息时是否使用了选择器。

    发布者与订阅者之间存在时间上的相关性:订阅者只有先订阅主题,才能接收到发布者在订阅者创建订阅后发布的消息。

消息消费

在JMS中,消息的产生和消费都是异步的。对于消费来说,JMS的消息者可以通过两种方式来消费消息。

  1. 同步
    订阅者或接收者通过receive方法来接收消息,receive方法在接收到消息之前(或超时之前)将一直阻塞;

  2. 异步
    订阅者或接收者可以注册为一个消息监听器。当消息到达之后,系统自动调用监听器的onMessage方法。

创建JMS应用程序

这里是用的ActiveMQ配合使用,过程其实和创建 JDBC 有点类似,下表为发送和接收消息所需的步骤

生成消息使用消息
管理员创建连接工厂受管理对象相同
客户端创建连接并设置特定于此连接的任何属性相同
客户端创建会话并设置用于决定消息传送可靠性的属性相同
客户端创建消息生成方客户端创建消息使用方
客户端创建消息客户端建立连接
客户端发送消息客户端接收消息
  1. 创建 连接工厂对象 (ConnectionFactory) 及 连接对象 Connecttion

    连接工厂封装了本地与MQ服务器之间的虚拟连接,并且可以配置从它派生的所有连接的行为,可以使用它来创建一个连接对象。

    public static final String BROKER_URL = "tcp://localhost:61616";
    // 创建连接工厂
    ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
    // 通过工厂创建一个连接
    connection = factory.createConnection();
    // 启动连接
    connection.start();
  2. 创建会话对象

    会话对象主要用于创建消息、消息生成方和消息使用方。创建会话时,通过多个确认选项或通过事务来配置可靠传送。

    // 创建一个session会话
    // 参数一:是否开启事务 true开启 ,false不开启事务,如果开启记得手动提交  
    // 参数二:签收模式,一般使用的有自动签收和客户端自己确认签收 
    session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
  3. 消息生产者

    通过会话会生成一个消息生产者,指定了发布消息类别:queue 或 topic
    可以设定消息的特性,是否持久化,到期时间,优先级等。

    // 创建名为 myQueue 队列
    Destination destination = session.createQueue(“myQueue”);
    // 创建名为 myTopic 主题
    //Destination destination = session.createTopic(“myTopic”);
    // 创建消息制作者
    MessageProducer producer = session.createProducer(destination);
    // 设置持久化模式
    producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
    //创建消息
    for (int i = 0; i < 6; i++) {
        String message = "发送消息第" + (i + 1) + "条";
        TextMessage text = session.createTextMessage(message);
        producer.send(text);
    }
  4. 消息消费者

    通过会话会生成一个消息消费者,指定了接收的消息类别:queue 或 topic
    可以设定消息的特性,是否持久化,到期时间,优先级等。

    // 创建名为 myQueue 队列
    Destination destination = session.createQueue(“myQueue”);
    // 创建名为 myTopic 主题
    //Destination destination = session.createTopic(“myTopic”);
    // 创建消息制作者
    MessageConsumer consumer = session.createConsumer(destination);
  5. 获取消息

    消息使用方可以支持同步或异步消息使用。

    • 同步

      表示使用方明确要求传送消息并使用该消息。

      根据请求消息时使用的方法,同步使用方可选择等待(无限期)消息到达,等待指定的时间或者在不存在可供使用的消息时立即返回。

      while (true) {
          // 接收数据的时间(等待) 10s
          Message message = consumer.receive(1000 * 10);
          TextMessage text = (TextMessage) message;
          if (text != null) {
              System.out.println("接收:" + text.getText());
          } else {
              break;
          }
      }
    • 异步

      表示自动将消息传送给为使用方注册的消息侦听器对象 (MessageListener)。当会话线程调用消息侦听器对象的 onMessage() 方法时,客户端将使用该消息。

      consumer.setMessageListener(new MessageListener() {
          public void onMessage(Message message) {
              try {
                  String text = ((TextMessage) message).getText();
                  System.out.println(text);
              } catch (JMSException e) {
                  e.printStackTrace();
              }
          }
      });

消息内容类型

在消息体中,JMS API定义了五种类型的消息格式,让我们可以以不同的形式发送和接受消息,并提供了对已有消息格式的兼容。不同的消息类型如下:

类型描述
TextMessage表示一个文本对象
ObjectMessage表示一个序列化 Java 对象的消息
BytesMessage表示字节数据
StreamMessage表示java原始值数据流
MapMessage表示键值对

特定于域的 API 及统一域 API

JMS API 定义可用于实现 点对点域 或 发布/订阅域 的接口和类。表的第 2 列和第 3 列中显示的特定于域的 API。JMS API 还定义另外一个统一域,用于通过编程实现常规的消息传送客户端。这类客户端的行为由目的地类型决定,客户端向目的地中生成消息并使用目的地中的消息。如果该目的地是一个队列,则消息传送行为将为点对点模式;如果该目的地是一个主题,则消息传送行为将为发布/订阅模式。

基本类型(统一域)点对点域发布/订阅域
Destination(队列或主题)QueueTopic
ConnectionFactoryQueueConnectionFactoryTopicConnectionFactory
ConnectionQueueConnectionTopicConnection
SessionQueueSessionTopicSession
MessageProducerQueueSenderTopicPublisher
MessageConsumerQueueReceiverTopicSubscriber
参考资料
  1. https://docs.oracle.com/cd/E19148-01/820-0533/aerbg/index.html
  2. https://docs.oracle.com/javaee/7/tutorial/partmessaging.htm#GFIRP3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ActiveMQ安装 : 1.下载:http://activemq.apache.org/download.html 最新Windows版本 2.配置jdk环境,解压ActiveMQ到本地 3.启动ActiveMQ服务器: 32位机 : 直接运行\bin\win32\activemq.bat 64位机 : 直接运行\bin\win64\activemq.bat 4.打开ActiveMQ消息管理后台系统 http://localhost:8161/admin/ 参考文章为 : HelloWorld : http://blog.csdn.net/baggio7095586/article/details/5708519 进阶 :http://haohaoxuexi.iteye.com/blog/1893038 helloworld阶段 : 一个发送消息的程序,一个接收消息的程序..实现最简单的JMS交流... 监听器阶段 : ⑴MessageListener,最简单的监听器..只是拿来监听接收信息的 ⑵SessionAwareMessageListener,有个session的参数..可以拿来对接收到的信息再做响应.. ⑶MessageListenerAdapter,将消息委托交给一个普通的java类来处理.. 转化器阶段 : 实现MessageConverter接口来转换JMS对象与java对象.. 其实在使用MessageListenerAdapter时,Spring默认为我们提供了SimpleMessageConverter转换器.. 事务(无代码): 在Spring整合JMS的应用中,如果我们要进行本地的事务管理的话非常简单,只需要在定义对应的消息监听容器时指定其sessionTransacted属性为true,如: <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory" /> <property name="destination" ref="queueDestination" /> <property name="messageListener" ref="consumerMessageListener" /> <property name="sessionTransacted" value="true"/> </bean> 该属性值默认为false,这样JMS在进行消息监听的时候就会进行事务控制,当在接收消息时监听器执行失败时JMS就会对接收到的消息进行回滚, 对于SessionAwareMessageListener在接收到消息后发送一个返回消息时也处于同一事务下,但是对于其他操作如数据库访问等将不属于该事务控制。 数据库跟JMS挂钩的事务先别理..
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值