最近同事在使用AMQ进行消息通信时遇到了问题:
在IE8中多个页面上访问AMQ的一个主题订阅的时候,多个页面中获得的消息其实是来自于同一个主题队列,导致页面状态逻辑错误.
查找AMQ的官方文档后得知,在5.4.2之后的版本中,AMQ的AJAX客户端可以通过指定唯一的clientId,让多个页面在一个浏览器中能够访问相同订阅的不同队列,避免了之前版本中只判断JSESSIONID导致的客户端无法区分的问题.官方文档在这里:
http://activemq.apache.org/ajax.html
但这里面实现的amq.js由于改动过大,无法与之前的接口兼容,所以并没有合并到官方主干源码中,只是以demo的形式额外存放.但实现上述功能的后端代码从5.4.2之后都被主干源码合并.
所以,单纯使用最新版的AMQ,是无法得到这个AJAX多客户端的功能的,需要自己额外进行调整.
今天上午解决了这个问题,稍稍修改了一下_amq.js文件,保证了与原接口的一致性,又增加了initClientId方法,可以方便的使用AMQ的AJAX多客户端功能了.
使用时,可以将这个_amq.js替换原activemq_web-x.x.x.jar中的文件,同时在调用页面中,进行最初uri赋值的时候,顺手调用一下amq.initClientId();就可以开启这个功能了.
刚刚进行代码测试,初步通过,功能的正确性得到了初步验证.
如果有同学遇到了相同的问题,希望能够帮忙进行测试调整.
文章系本人原创,转载请注明出处和作者
,本文原址在http://h-rain.iteye.com/blog/1387640
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// AMQ Ajax handler
// This class provides the main API for using the Ajax features of AMQ. It
// allows JMS messages to be sent and received from javascript when used
// with the org.apache.activemq.web.MessageListenerServlet
//
var amq =
{
// The URI of the MessageListenerServlet
uri: '/amq',
// Polling. Set to true (default) if waiting poll for messages is needed
poll: true,
// Poll delay. if set to positive integer, this is the time to wait in ms before
// sending the next poll after the last completes.
_pollDelay: 0,
_clientIdStr:'',
_first: true,
_pollEvent: function(first) {},
_handlers: new Array(),
_messages:0,
_messageQueue: '',
_queueMessages: 0,
//init the clientId,default auto make as Date string
initClientId:function(newId)
{
if (newId)
amq._clientIdStr="clientId="+newId;
else
amq._clientIdStr="clientId="+(new Date()).getTime().toString();
},
//using clientId,whit separtor
_makeClientIdStr:function(spChar)
{
var SC=spChar||'';
if (amq._clientIdStr=='')
return '';
return SC+amq._clientIdStr;
},
_messageHandler: function(request)
{
try
{
if (request.status == 200)
{
var response = request.responseXML.getElementsByTagName("ajax-response");
if (response != null && response.length == 1)
{
for ( var i = 0 ; i < response[0].childNodes.length ; i++ )
{
var responseElement = response[0].childNodes[i];
// only process nodes of type element.....
if ( responseElement.nodeType != 1 )
continue;
var id = responseElement.getAttribute('id');
var handler = amq._handlers[id];
if (handler!=null)
{
for (var j = 0; j < responseElement.childNodes.length; j++)
{
handler(responseElement.childNodes[j]);
}
}
}
}
}
}
catch(e)
{
alert(e);
}
},
startBatch: function()
{
amq._queueMessages++;
},
endBatch: function()
{
amq._queueMessages--;
if (amq._queueMessages==0 && amq._messages>0)
{
var body = amq._messageQueue;
amq._messageQueue='';
amq._messages=0;
amq._queueMessages++;
new Ajax.Request(amq.uri, { method: 'post', postBody: body+amq._makeClientIdStr('&'), onSuccess: amq.endBatch});
}
},
_pollHandler: function(request)
{
amq.startBatch();
try
{
amq._messageHandler(request);
amq._pollEvent(amq._first);
amq._first=false;
}
catch(e)
{
alert(e);
}
amq.endBatch();
if (amq._pollDelay>0)
setTimeout('amq._sendPoll()',amq._pollDelay);
else
amq._sendPoll();
},
_sendPoll: function(request)
{
new Ajax.Request(amq.uri, { method: 'get', parameters: amq._makeClientIdStr(),onSuccess: amq._pollHandler });
},
// Add a function that gets called on every poll response, after all received
// messages have been handled. The poll handler is past a boolean that indicates
// if this is the first poll for the page.
addPollHandler : function(func)
{
var old = amq._pollEvent;
amq._pollEvent = function(first)
{
old(first);
func(first);
}
},
// Send a JMS message to a destination (eg topic://MY.TOPIC). Message should be xml or encoded
// xml content.
sendMessage : function(destination,message)
{
amq._sendMessage(destination,message,'send');
},
// Listen on a channel or topic. handler must be a function taking a message arguement
addListener : function(id,destination,handler)
{
amq._handlers[id]=handler;
amq._sendMessage(destination,id,'listen');
},
// remove Listener from channel or topic.
removeListener : function(id,destination)
{
amq._handlers[id]=null;
amq._sendMessage(destination,id,'unlisten');
},
_sendMessage : function(destination,message,type)
{
if (amq._queueMessages>0)
{
if (amq._messages==0)
{
amq._messageQueue='destination='+destination+'&message='+message+'&type='+type;
}
else
{
amq._messageQueue+='&d'+amq._messages+'='+destination+'&m'+amq._messages+'='+message+'&t'+amq._messages+'='+type;
}
amq._messages++;
}
else
{
amq.startBatch();
new Ajax.Request(amq.uri, { method: 'post', postBody: 'destination='+destination+'&message='+message+'&type='+type+amq._makeClientIdStr('&'), onSuccess: amq.endBatch});
}
},
_startPolling : function()
{
if (amq.poll)
new Ajax.Request(amq.uri, { method: 'get', parameters: 'timeout=10'+amq._makeClientIdStr('&'), onSuccess: amq._pollHandler });
}
};
Behaviour.addLoadEvent(amq._startPolling);
function getKeyCode(ev)
{
var keyc;
if (window.event)
keyc=window.event.keyCode;
else
keyc=ev.keyCode;
return keyc;
}
分享到:
相关推荐
内容概要:本文介绍了EPLAN史上最全部件库的特点及其对电气设计的重要意义。该部件库涵盖了广泛的电气元件,包括西门子全系列PLC(如s7-1200、s7-1500等)、三菱FX系列及其他知名品牌元器件。部件库支持EDZ格式导入,确保1:1实物对应,提高设计效率和准确性。文中详细描述了部件宏和图片宏的应用,以及EDZ格式的便利性,强调了其在实际项目中的高效性和灵活性。 适合人群:电气工程师、电气设计师及相关从业人员。 使用场景及目标:适用于需要进行电气元件布局和复杂项目电气设计的场合,旨在提升设计质量和效率,降低设计成本和时间。 其他说明:文章鼓励读者亲自体验EPLAN的最全部件库,以感受其带来的便捷和高效。
内容概要:本文详细介绍了OCR(光学字符识别)技术,从定义出发,阐述了它是如何让计算机“看懂”图片里的文字,通过扫描仪等设备读取文本图像并转换成计算机可编辑的文本。文中列举了OCR在办公、图书馆、交通、金融等领域的广泛应用实例,如快速处理纸质文件、车牌识别、银行支票处理等。接着回顾了OCR的发展历程,从20世纪初的萌芽到如今基于深度学习的智能化时代,期间经历了从简单字符识别到复杂场景下的高精度识别的演变。技术层面,深入解析了OCR的关键技术环节,包括图像预处理、文本检测、文本识别和后处理,每个环节都采用了先进的算法和技术手段以确保识别的准确性。最后探讨了OCR在未来可能面临的挑战,如复杂场景下的识别准确率、特殊字体和语言的支持以及数据安全问题,并展望了其与人工智能融合后的广阔前景。 适合人群:对OCR技术感兴趣的技术爱好者、开发者以及希望了解该技术在各行业应用的专业人士。 使用场景及目标:①帮助用户理解OCR技术的基本原理和发展历程;②展示OCR在多个行业中的具体应用场景,如办公自动化、金融票据处理、医疗病历管理等;③探讨OCR技术面临的挑战及未来发展方向,为相关从业者提供参考。 其他说明:本文不仅涵盖了OCR技术的基础知识,还深入探讨了其背后的技术细节和发展趋势,对于想要深入了解OCR技术及其应用的人来说是非常有价值的参考资料。
实训商业源码-教育培训学校 1.5.9-论文模板.zip
内容概要:本文档是关于ArkUI-X跨平台框架的接入指南,ArkUI-X能够支持OpenHarmony、Android、iOS等多个操作系统平台,让开发者用一套主代码构建多平台的高性能应用。文中详细介绍了使用DevEco Studio开发ArkUI-X的约束条件,包括各平台的版本及构建工具要求;还提供了安装ArkUI-X SDK的具体步骤,如在DevEco Studio的设置中指定SDK存储路径等;对于Android SDK安装目录环境变量的配置,针对Windows和macOS给出了详细的设置方法;创建工程方面,介绍了从创建跨平台模版工程到编译构建生成跨平台应用的一系列操作;最后简述了多端运行效果,即在不同平台上运行生成的应用查看效果。; 适合人群:有一定开发经验,特别是对跨平台应用开发感兴趣的开发者。; 使用场景及目标:①希望快速掌握ArkUI-X框架,利用一套代码构建适用于多个操作系统的应用程序;②熟悉DevEco Studio开发环境及其相关配置,如SDK安装、环境变量设置等;③了解如何创建、编译构建跨平台应用并在不同平台上运行查看效果。; 阅读建议:由于涉及较多的操作步骤和配置细节,在阅读时应仔细按照文档指引进行实践操作,确保每一步骤正确无误,遇到问题可以通过查阅官方文档或社区寻求帮助。
实训商业源码-多彩记账本 1.1.9-论文模板.zip
实训商业源码-淘客5.99.65完整包-论文模板.zip
实训商业源码-[15950]【在线解析API网页源码】在线随机图片+网易云音乐解析API网页源码-论文模板.zip
实训商业源码-最新抽奖助手 5.2.3-论文模板.zip
内容概要:本文详细探讨了分段斜坡补偿电路在BOOST(升压)和BUCK(降压)系统中的应用。首先介绍了这两种常见直流电源转换器的基本特性及其应用场景。接着阐述了分段斜坡补偿电路的工作原理,即通过引入斜坡补偿信号来动态调整开关时序,从而优化开关过程,减少电压和电流冲击,提升系统性能。对于BOOST系统,分段斜坡补偿电路能有效控制升压开关的时间,降低损耗并提高转换效率;而在BUCK系统中,则通过精准控制降压开关时间,确保输出电压的稳定性。最后总结了分段斜坡补偿电路带来的多项优势,如增强系统稳定性、降低损耗、适应多种负载条件以及加快响应速度。 适用人群:从事电力电子设计的技术人员,尤其是专注于电源管理模块设计的研发人员。 使用场景及目标:适用于需要深入了解BOOST和BUCK系统内部机制及其改进方法的研究者和技术开发者,旨在帮助他们掌握分段斜坡补偿电路的具体应用技巧,进而改善相关产品的性能。 其他说明:随着电力电子技术的发展,分段斜坡补偿电路有望在未来更多类型的电源转换器中发挥作用,推动整个行业向更高水平发展。
毕业设计-云档新版小程序端,基于mpvue开发cloud-doc-v2-整站商业源码.zip
内容概要:本文详细介绍了MPC(模型预测控制)在Matlab Simulink与Carsim联合仿真中的具体应用,重点讲解了.cpar文件的配置方法及其内部结构,强调了路径同步、单位转换以及预测步长设置等问题。文中提到,.cpar文件包含了车辆底盘参数、轮胎特性、空气动力学等配置,可以通过解压工具查看并修改其中的XML文件。同时,文章指出,在Matlab中进行路径同步时需要注意相对路径的问题,并提供了具体的代码示例。此外,文章还提到了方向单位从度到弧度的转换问题,以及MPC控制器模块预测步长的设定对仿真效果的影响。最后,作者分享了一些调试技巧,如利用Simulink的Signal Logging功能来捕获中间变量,以便更好地优化仿真性能。 适合人群:从事汽车仿真研究的技术人员,尤其是熟悉Matlab Simulink和Carsim的用户。 使用场景及目标:帮助用户掌握MPC模型预测控制在联合仿真中的配置和调试方法,提高仿真的准确性和效率。 其他说明:文章不仅提供了理论指导,还结合实际案例进行了详细的解释,使读者能够快速理解和应用相关技术。
内容概要:本文介绍了Elasticsearch(简称ES),这是一个基于Apache Lucene开发的开源、分布式、RESTful风格的搜索和数据分析引擎。Elasticsearch能够对海量结构化和非结构化数据进行实时存储、搜索和分析,广泛应用于全文检索、日志分析、数据可视化等场景。其核心原理是以文档为核心,采用倒排索引技术提升全文检索效率,并支持分布式架构,确保高可用性和可扩展性。主要功能包括全文检索、结构化查询、实时分析和分布式存储,通过RESTful API进行数据管理。优点涵盖高性能的全文检索和分析能力、易于扩展的分布式架构、丰富的查询DSL和聚合功能以及活跃的社区生态;缺点则在于对硬件要求较高,集群管理和调优有一定门槛,对强一致性事务支持有限。; 适合人群:对搜索引擎技术感兴趣的开发者、大数据分析师、运维工程师等。; 使用场景及目标:①网站和应用的全文搜索;②日志和运维数据分析(如ELK Stack);③电商商品检索;④数据可视化和BI分析;⑤推荐系统和个性化内容推送。; 其他说明:Elasticsearch凭借其强大的检索和分析能力,成为大数据时代不可或缺的基础组件,适用于互联网企业及传统行业的数据驱动业务场景。
实训商业源码-仿扎克新闻mpZAKER-论文模板.zip
小麦病害检测数据集VOC+YOLO格式1882张4类别.docx
内容概要:文章介绍了谷歌推出的AI聊天机器人Bard的发展历程、独特优势、应用场景及其面临的挑战。Bard基于谷歌的LaMDA模型开发,虽然初期因回答错误受到质疑,但在引入PaLM 2后,其性能大幅提升,支持多种语言并增强了图像生成和与谷歌办公软件的集成。Bard在自然语言处理、跨领域知识整合和隐私保护方面表现出色,广泛应用于教育、科研和商业领域。与ChatGPT和GPT-4相比,Bard在对话场景、数据时效性和特定领域知识上有优势。尽管面临准确性、伦理和市场竞争的挑战,Bard仍展现了巨大的发展潜力,未来将在智能家居、智能交通和艺术创作等领域发挥更大作用。 适合人群:对人工智能技术感兴趣的人士,包括学生、科研人员、企业管理人员和技术爱好者。 使用场景及目标:①了解AI聊天机器人的发展历程和技术进步;②探索Bard在教育、科研、商业等领域的具体应用;③对比Bard与其他AI聊天机器人的优劣势;④思考AI技术的未来发展和潜在挑战。 阅读建议:本文详细介绍了Bard的技术特点和应用场景,读者可以通过对比不同AI聊天机器人的优缺点,深入了解AI技术的现状和发展趋势。同时,文中提到的挑战也值得思考,帮助读者更全面地理解AI技术的复杂性和未来发展方向。
LD房地产项目应用蒙特卡洛模拟法的投资风险评估研究_王宓
小目标检测_基于红外图像实现的小目标检测算法_附项目源码+流程教程_优质项目实战
图像增强_基于红外编码实现的低光图像增强算法_附项目源码_优质项目实战