ActiveMQ教程(4)— JMS和协议间转换

标签: ActiveMQ Openwire JMS 消息队列
14人阅读 评论(0) 收藏 举报
分类:

JMS这套面向消息通信的 JAVA API 是一个和厂商无关的规范。通过JMS,我们能实现不同消息中间件厂商、不同协议间的转换和交互。这一小节我们就来讨论一下这个问题。如果用一张图来表示JMS在消息中间件中的作用话,那么就可以这么来画:
这里写图片描述
首先,使用的MQ消息中间件需要实现了JMS规范;那么通过JMS规范,开发人员可以忽略各种消息协议的细节,只要消息在同一队列中,就能够保证各种消息协议间实现互相转换。

下面:

  • 首先,来看一个使用JMS API在ActiveMQ中操作openwire协议消息的简单示例;
  • 然后,再给出一个通过JMS,实现Stomp消息协议和Openwire消息协议间的互转示例。

JMS操作


以下代码向某个Queue(命名为test)中发送一条消息:

package jms;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;


/**
 * 测试使用JMS API连接ActiveMQ
 */
public class JMSProducer {

    /**
     * 由于是测试代码,这里忽略了异常处理。 正式代码可不能这样做
     */
    public static void main(String[] args) throws Exception {
        // 定义JMS-ActiveMQ连接信息(默认为Openwire协议)
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.1.128:61616");
        Session session = null;
        Destination sendQueue;
        Connection connection = null;

        // 进行连接
        connection = connectionFactory.createQueueConnection();
        connection.start();

        // 建立会话(设置一个带有事务特性的会话)
        session = connection.createSession(true, Session.SESSION_TRANSACTED);
        // 建立queue(当然如果有了就不会重复建立)
        sendQueue = session.createQueue("/test");
        // 建立消息发送者对象
        MessageProducer sender = session.createProducer(sendQueue);
        TextMessage outMessage = session.createTextMessage();
        outMessage.setText("这是发送的消息内容");

        // 发送(JMS是支持事务的)
        sender.send(outMessage);
        session.commit();

        // 关闭
        sender.close();
        connection.close();
    }
}

当以上代码运行到“start”的位置时,我们可以通过观察ActiveMQ管理界面中connection列表中的连接信息,发现消息生产者已经建立了一个Openwire协议的连接:
这里写图片描述
从而确定我们通过JMS API建立了一个openwire协议的通讯连接。接着我们使用以下代码,建立一个基于openwire协议的“消费者”。注意:消息生产者和消息消费者,映射的队列必须一致。(在示例代码中,它们都映射名称为test的JMS-Queue)

以下代码使用JMS从某个Queue中接收消息:

package jms;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;

import javax.jms.Session;

import org.apache.activemq.ActiveMQConnectionFactory;


/**
 * 测试使用JMS API连接ActiveMQ
 */
public class JMSConsumer {

    /**
     * 由于是测试代码,这里忽略了异常处理。 正式代码可不能这样做
     */
    public static void main(String[] args) throws Exception {
        // 定义JMS-ActiveMQ连接信息
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.1.128:61616");
        Session session = null;
        Destination sendQueue;
        Connection connection = null;

        // 进行连接
        connection = connectionFactory.createQueueConnection();
        connection.start();

        // 建立会话(设置为自动ack)
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        // 建立Queue(当然如果有了就不会重复建立)
        sendQueue = session.createQueue("/test");
        // 建立消息消费者对象
        MessageConsumer consumer = session.createConsumer(sendQueue);
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                // 接收到消息后,不需要再发送ack了。
                System.out.println("Message = " + message);
            }
        });

        synchronized (JMSConsumer.class) {
            JMSConsumer.class.wait();
        }

        // 关闭
        consumer.close();
        connection.close();
    }
}

当以上“消费者”代码运行到start的位置时,我们通过ActiveMQ提供的管理界面可以看到,基于Openwire协议的连接增加到了两条:
这里写图片描述
注意,您在运行以上测试代码时,不用和我的运行顺序一致。由于Queue模式的队列是要进行消息状态保存的,所以无论您是先运行“消费者”端,还是先运行“生产者”端,最后“消费者”都会收到一条消息。类似如下的效果:

Message = ActiveMQTextMessage {commandId = 6, responseRequired = false, messageId = ID:ChaoSaiShen-50923-1523943611554-1:1:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:ChaoSaiShen-50923-1523943611554-1:1:1:1, destination = queue:///test, transactionId = TX:ID:ChaoSaiShen-50923-1523943611554-1:1:1, expiration = 0, timestamp = 1523943611730, arrival = 0, brokerInTime = 1523943613808, brokerOutTime = 1523943613812, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@7d77e501, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false, text = 这是发送的消息内容}

协议间转换


下面我们将Openwire协议的消息通过JMS送入Queue队列,并且让基于Stomp协议的消费者接收到这条消息。为了节约篇幅,基于Openwire协议的生产者的代码请参考上面“生产者”的代码片段。这里只列出Stomp消息的接受者代码:

Stomp协议的消息消费者(消息接收者):

package jms;

import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Map;

import org.apache.activemq.transport.stomp.StompConnection;
import org.apache.activemq.transport.stomp.StompFrame;

public class TestConsumer {
    public static void main(String[] args) throws Exception {
        // 建立连接(注意,Stomp协议的连接端口是61613)
        StompConnection con = new StompConnection();
        Socket so = new Socket("192.168.1.128", 61613);
        con.open(so);
        con.setVersion("1.2");
        con.connect("admin", "admin");

        String ack = "client";
        con.subscribe("/test", "client");
        // 接受消息(使用循环进行)
        for (;;) {
            StompFrame frame = null;
            try {
                // 注意,如果没有接收到消息,
                // 这个消费者线程会停在这里,直到本次等待超时
                frame = con.receive();
            } catch (SocketTimeoutException e) {
                continue;
            }

            // 打印本次接收到的消息
            System.out.println("frame.getAction() = " + frame.getAction());
            Map<String, String> headers = frame.getHeaders();
            String meesage_id = headers.get("message-id");
            System.out.println("frame.getBody() = " + frame.getBody());
            System.out.println("frame.getCommandId() = " + frame.getCommandId());

            // 在ack是client模式的情况下,确认消息
            if ("client".equals(ack)) {
                con.ack(meesage_id);
            }
        }
    }
}

当您同时运行Openwire消息发送者和Stomp消息接收者时,您可以在ActiveMQ的管理界面看到这两种协议的连接信息:
这里写图片描述

以下是Stomp协议消费者接收到的消息内容(经过转换的openwire协议消息):

frame.getAction() = MESSAGE
frame.getBody() = 这是发送的消息内容
frame.getCommandId() = 0




文章来源:https://blog.csdn.net/yinwenjie/article/details/50916518

查看评论

JMS学习八(ActiveMQ支持的传输协议)

ActiveMQ提供了一种连接机制,这种连接机制使用传输连接器(TransportConnector)实现客户端与代理(client - to - broker)之间的通信。 网络连接器(networ...
  • QH_JAVA
  • QH_JAVA
  • 2017-03-10 16:59:03
  • 1054

深入浅出JMS(三)--ActiveMQ简单的HelloWorld实例

JMS其实并没有想象的那么高大上,看完这篇博文之后,你就知道什么叫简单。。...
  • jiuqiyuliang
  • jiuqiyuliang
  • 2015-09-26 13:37:47
  • 97220

Java ActiveMQ 理解JMS 和 ActiveMQ基本使用

最近的项目中用到了mq,之前自己一直在码农一样的照葫芦画瓢。最近几天研究了下,把自己所有看下来的文档和了解总结一下。 一. 认识JMS 1.概述 对于JMS,百度百科,是这样介绍的:...
  • JameBing
  • JameBing
  • 2016-11-24 15:35:46
  • 19455

MQ、JMS以及ActiveMQ 关系的理解

MQ、JMS以及ActiveMQ 分类: ActiveMQ2013-06-19 13:58 1660人阅读 评论(5) 收藏 举报 MQJMSActiveMQ MQ简介: ...
  • zzjjiandan
  • zzjjiandan
  • 2014-04-15 11:14:03
  • 32515

一头扎进 JMS 之 ActiveMQ 视频教程

一头扎进 JMS 之 ActiveMQ 视频教程参考“www.java1234.com”视频,适合入门,只简单d介绍工作的中常用的两种方式1:点对点消息实现,2:发布-订阅消息模式实现...
  • kinbridge
  • kinbridge
  • 2016-09-25 15:23:00
  • 2795

JMS+activeMq+spring简单学习及模拟处理新闻日志场景

学习jms+activeMq+spring过程中的一些整理
  • dream_broken
  • dream_broken
  • 2015-02-13 10:55:57
  • 1501

JMS之ActiveMQ视频教程

  • 2017年11月09日 13:58
  • 48B
  • 下载

JMS消息传送机制ActiveMQ

JMS(Java Message Service) 消息服务是一个面向消息中间件(MOM)的API,用于在两个应用程序之间,或者分布式系统中发送消息消费消息,进行异步通信,数据交互。JMS提供的API...
  • manmanxiaohui
  • manmanxiaohui
  • 2016-10-11 21:54:11
  • 1721

ActiveMQ之spring集成消息转换器MessageConverter

MessageConverter的作用主要有两方面,一方面它可以把我们的非标准化Message对象转换成我们的目标Message对象,这主要是用在发送消息的时候;另一方面它又可以把我们的Message...
  • tianwei7518
  • tianwei7518
  • 2015-06-01 11:45:08
  • 2977

jms之activeMQ与spring集成进阶-实现一种负载均衡

做了一个关于jms的负载均衡的项目,做完之后颇有打通任督二脉的感觉,感觉很多之前不是很理解的东西,都有些理解了,比如服务器端的监听、具体的jms的使用等,收获有点大。 流程如下图所示: ...
  • zmx729618
  • zmx729618
  • 2016-07-19 11:29:27
  • 1569
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 2万+
    积分: 1970
    排名: 2万+
    博客专栏
    文章存档
    最新评论