2008-10-27
關於 Portfolio 範例
- 下載 ActiveMQ 5.1.0 Release, 解壓縮,並執行 ActiveMQ Message Broker
~$ wget http://ftp.twaren.net/Unix/Web/apache/activemq/apache-activemq/5.1.0/apache-activemq-5.1.0-bin.tar.gz ~$ tar zxvf apache-activemq-5.1.0-bin.tar.gz ~$ cd apache-activemq-5.1.0/ ~/apache-activemq-5.1.0$ ./bin/activemq
- 連線到 http://127.0.0.1:8161/demo/
- 用不同的視窗執行 Portfolio 範例,下圖右上方是"Market data publisher"網頁(Message Provider),左上方是"Portfolio"網頁(Message Receiver),下方是 ActiveMQ Message Broker。我們可以看到 Message Sender/Provider? 網頁每兩秒送出一筆新的訊息。而 Message Receiver/Subscriber? 則會用顏色標示出目前更新的情形。
- 連線到 http://127.0.0.1:8161/admin/topics.jsp 可以查詢不同的 Topic 各有傳送接收多少個訊息。
- 這個範例證實了 ActiveMQ 可以用 JavaScript 實做出加入 Message Broker 後即時更新的可能性,因此值得追蹤其背後的原理。
追蹤原始碼(1) - Message Sender / Provider
- "Market data publisher"網頁(Message Provider)的網址比較特殊,是 "portfolioPublish?count=1&refresh=2&stocks=IBMW&stocks=BEAS&stocks=MSFT&stocks=SUNW",直接觀看 HTML 原始碼並沒有 JavaScript 的蹤影,因此它應該是 JSP 網頁。而在 apache-activemq-5.1.0\webapps\demo\WEB-INF\web.xml 中,我們就可以找到答案了~
<!-- servlets for the portfolio demo --> <servlet> <servlet-name>PortfolioPublishServlet</servlet-name> <servlet-class>org.apache.activemq.web.PortfolioPublishServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> ... 略 ... <servlet-mapping> <servlet-name>PortfolioPublishServlet</servlet-name> <url-pattern>/portfolioPublish</url-pattern> </servlet-mapping>
- 因此,"Market data publisher"網頁(Message Provider)的原始碼必須看 activemq.jar 裡包的 PortfolioPublishServlet.class 對應的原始碼。
- 請下載 ActiveMQ 5.1.0 Source Release
~$ wget http://ftp.twaren.net/Unix/Web/apache/activemq/apache-activemq/5.1.0/apache-activemq-5.1.0-src.tar.gz ~$ tar zxvf apache-activemq-5.1.0-src.tar.gz ~$ cd apache-activemq-5.1.0/src/activemq-web/src/main/java/org/apache/activemq/web/ ~$ vi PortfolioPublishServlet.java
- 路徑: apache-activemq-5.1.0/src/activemq-web/src/main/java/org/apache/activemq/web/PortfolioPublishServlet.java
追蹤原始碼(2) - Message Subsciber / Receiver
- 觀察"Portfolio"網頁(Message Receiver)的原始碼
<script type="text/javascript" src="../amq/amq.js"></script> <script type="text/javascript">amq.uri='../amq';</script> <script type="text/javascript" src="portfolio.js"></script>
- 下載所有相關的 JavaScript 原始碼
~$ wget http://127.0.0.1:8161/demo/portfolio/portfolio.js ~$ wget http://127.0.0.1:8161/demo/amq/amq.js
- 從 amq.js 又可以找出其他 JavaScript 原始碼
var _AMQ_INCLUDE = { Version: 'AMQ JS', script: function(libraryName) { document.write('<script type="text/javascript" src="'+libraryName+'"></script>'); }, load: function() { var scriptTags = document.getElementsByTagName("script"); for(var i=0;i<scriptTags.length;i++) { if(scriptTags[i].src && scriptTags[i].src.match(/amq\.js$/)) { var path = scriptTags[i].src.replace(/amq\.js$/,''); this.script(path + 'prototype.js'); this.script(path + 'behaviour.js'); this.script(path + '_amq.js'); // this.script(path + 'scriptaculous.js'); break; } } } } _AMQ_INCLUDE.load();
- 下載其他 JavaScript 原始碼
~$ wget http://127.0.0.1:8161/demo/amq/prototype.js ~$ wget http://127.0.0.1:8161/demo/amq/behaviour.js ~$ wget http://127.0.0.1:8161/demo/amq/_amq.js
- 其中 prototype.js 跟 behaviour.js 都是跟 AJAX 與 CSS 相關的 JavaScript Framework
- prototype.js - Prototype JavaScript framework, version 1.4.0 - 目前已經是 1.6.0.3 版了!
- 剩下 portfolio.js 跟 _amq.js 是比較重要的兩個 script. 首先來看 portfolio.js
// 註冊 PollHandler // 參考: _amq.js - addPollHandler : function(func) // * func: 函數指標(Function Pointer) amq.addPollHandler(portfolioPoll); // 這裡的 first 定義在 _amq.js 裡,預設值 _first: true function portfolioPoll(first) { if (first) { // 參考: _amq.js - addListener : function(id,destination,handler) // * id: Handler id // * destination: Listen to a Message Channel or Topic // * handler: 函數指標, 發生事件時的 callback 函數, 必須能處理 message 函數 amq.addListener('stocks','topic://STOCKS.*',priceHandler._price); } } // priceHandler 類別的 _price 函數宣告 var priceHandler = { _price: function(message) // 剩下的部份就是在處理 message 中的資料,忽略不看 }
- _amq.js
// 一開始載入時會透過 Behaviour 啟動 amq._startPolling Behaviour.addLoadEvent(amq._startPolling); var amq = { uri: '/amq', // 這在 portfolio.html 中已被取代為 amq.uri='../amq' poll: true, // 預設 poll 為 true _startPolling : function() { if (amq.poll) // 預設 amq.poll 為 true // 產生 AJAX Request // 參考: prototype.js - Ajax.Request(url, options) = 建構子(Constructor) // // 626 Ajax.Request.prototype = Object.extend(new Ajax.Base(), { // 627 initialize: function(url, options) { // // 這裡的意思是當 AJAX XmlHttpRequest 完成 get amq.uri 時,執行 amq._pollHandler new Ajax.Request(amq.uri, { method: 'get', parameters: 'timeout=0', onSuccess: amq._pollHandler }); } _pollHandler: function(request) { amq.startBatch(); try { amq._messageHandler(request); amq._pollEvent(amq._first); // amq._pollEvent 等同於呼叫 portfolio.js 的 portfolioPoll(first) amq._first=false; } catch(e) { alert(e); } amq.endBatch(); if (amq._pollDelay>0) setTimeout('amq._sendPoll()',amq._pollDelay); else amq._sendPoll(); }, startBatch: function() { amq._queueMessages++; }, _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); } }, 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, onSuccess: amq.endBatch}); } },
Last modified 16 years ago
Last modified on Feb 16, 2009, 1:44:23 PM
Attachments (9)
- ActiveMQ_Sample.png (49.3 KB) - added by jazz 16 years ago.
- ActiveMQ_Portfolio.png (169.8 KB) - added by jazz 16 years ago.
- ActiveMQ_Admin.png (90.1 KB) - added by jazz 16 years ago.
- PortfolioPublishServlet.java (5.1 KB) - added by jazz 16 years ago.
- prototype.js (46.5 KB) - added by jazz 16 years ago.
- behaviour.js (7.7 KB) - added by jazz 16 years ago.
- amq.js (1.5 KB) - added by jazz 16 years ago.
- _amq.js (5.1 KB) - added by jazz 16 years ago.
- portfolio.js (2.5 KB) - added by jazz 16 years ago.
Download all attachments as: .zip