ActiveMQ系列—JMS和协议间转换(代码示例)
来源:互联网 发布:switch php case 多个 编辑:程序博客网 时间:2024/06/07 05:06
JMS这套面向消息通信的 JAVA API 是一个和厂商无关的规范。通过JMS,我们能实现不同消息中间件厂商、不同协议间的转换和交互。这一小节我们就来讨论一下这个问题。如果用一张图来表示JMS在消息中间件中的作用话,那么就可以这么来画:
首先您使用的MQ消息中间件需要实现了JMS规范;那么通过JMS规范,开发人员可以忽略各种消息协议的细节,只要消息在同一队列中,就能够保证各种消息协议间实现互相转换。
下面我们首先来看一个使用JMS API在ActiveMQ中操作openwire协议消息的简单示例,然后再给出一个通过JMS,实现Stomp消息协议和Openwire消息协议间的互转示例。
1、JMS操作
以下代码使用JMS向某个Queue(命名为test)中发送一条消息:
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.168: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中接收消息:
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.168: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 arg0) { // 接收到消息后,不需要再发送ack了。 System.out.println("Message = " + arg0); } }); synchronized (JMSConsumer.class) { JMSConsumer.class.wait(); } // 关闭 consumer.close(); connection.close(); }}
当以上“消费者”代码运行到start的位置时,我们通过ActiveMQ提供的管理界面可以看到,基于Openwire协议的连接增加到了两条:
注意,您在运行以上测试代码时,不用和我的运行顺序一致。由于Queue模式的队列是要进行消息状态保存的,所以无论您是先运行“消费者”端,还是先运行“生产者”端,最后“消费者”都会收到一条消息。类似如下的效果:
Message = ActiveMQTextMessage {commandId = 6, responseRequired = false, messageId = ID:DESKTOP-OI6HIIK-50405-1505802774972-1:1:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:DESKTOP-OI6HIIK-50405-1505802774972-1:1:1:1, destination = queue:///test, transactionId = TX:ID:DESKTOP-OI6HIIK-50405-1505802774972-1:1:1, expiration = 0, timestamp = 1505802957605, arrival = 0, brokerInTime = 1505802957612, brokerOutTime = 1505802957617, 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@54ba93f3, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false, text = 这是发送的消息内容}
2、协议间转换
下面我们将Openwire协议的消息通过JMS送入Queue队列,并且让基于Stomp协议的消费者接收到这条消息。为了节约篇幅,基于Openwire协议的生产者的代码请参考上一小节中“生产者”的代码片段。这里只列出Stomp消息的接受者代码:
Stomp协议的消息消费者(消息接收者):
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.168", 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() = MESSAGEframe.getBody() = 这是发送的消息内容frame.getCommandId() = 0
- ActiveMQ系列—JMS和协议间转换(代码示例)
- ActiveMQ系列—JMS规范
- JMS ActiveMQ 示例
- JMS-ActiveMQ系列
- ActiveMQ系列—消息协议(XMPP协议)
- ActiveMQ系列—消息协议(Stomp协议)
- ActiveMQ系列—消息协议(AMQP协议)
- ActiveMQ系列之三:理解和掌握JMS
- JMS和ActiveMQ
- ActiveMQ和JMS介绍
- JMS和ActiveMQ
- JMS和ActiveMQ
- JMS 和 ActiveMQ
- JMS和ActiveMQ入门
- JMS学习八(ActiveMQ支持的传输协议)
- ActiveMQ系列—JMS规范中的几个基本概念
- 消息队列系列之ActiveMQ(JMS、集群配置)
- ActiveMQ(一)——JMS概要
- ue4 材质翻转法线开关控制
- 虚拟机优化参数
- springboot分表sharding-jdbc-core
- Android 插件化基础——虚拟机
- 反-反爬虫:用几行代码写出和人类一样的动态爬虫
- ActiveMQ系列—JMS和协议间转换(代码示例)
- 云朵后台接口文档
- 在HBuilder中采用百度地图动态画轨迹
- 系统相机拍照、从相册中获取图片
- 前端知识体系目录
- anaconda下安装opencv
- 使用 VPS 搭建私有云并通过「区块存储」扩充空间
- 线程堆栈分析
- 9月18日云栖精选夜读:「阿里巴巴编码规范(Java版)」认证考试出炉!你考过了吗?