首先我们需要去了解一下pushlet的代码,从而进行我们自己的自定义需求,首先我们找到我们写的后台服务,有两个方法一个设置睡眠时间和生成事件,那么到底有什么用呢,哪里用到了呢。我们将从官网下载的源码也放入到项目中去,我们进入到HelloWorldPlushlet继承的EventPullSource类里面,原来它继承了Runnable,是个线程,那么查看run方法:发现这里用到了我们自定义的两个方法,通过设置的睡眠时间让线程睡眠,一个通过生成事件的方法生成事件并且发布出去,那么到这里我们大概明白了,原来pushlet后台是生成了一个线程,这个线程不断生成事件并且发布出去,然后睡眠,一直循环。这就是生产信息的那个线程。
/** * Main loop: sleep, generate event and publish. */ public void run() { Log.debug(getClass().getName() + ": starting..."); alive = true; while (alive) { try { Thread.sleep(getSleepTime()); // Stopped during sleep: end loop. if (!alive) { break; } // If passivated wait until we get // get notify()-ied. If there are no subscribers // it wasts CPU to remain producing events... synchronized (this) { while (!active) { Log.debug(getClass().getName() + ": waiting..."); wait(); } } } catch (InterruptedException e) { break; } try { // Derived class should produce an event. Event event = pullEvent(); // Let the publisher push it to subscribers. Dispatcher.getInstance().multicast(event); } catch (Throwable t) { Log.warn("EventPullSource exception while multicasting ", t); t.printStackTrace(); } } Log.debug(getClass().getName() + ": stopped"); } }
那么前台是怎么访问的呢,我们打开浏览器f12看看前台都发送了哪些请求:
第三个和第四个都有pushlet.srv,是不是很眼熟,这不就是我们前面web.xml配置的链接,这两个链接都是pushlet servlet管理了,第三个链接就是前台告诉pushlet我监控了什么事件了,第四链接是每次经过定时时间,都会发送这个链接,很明显这是用来接收后台的生产线程消息的。好到这里我们大体了解了流程,后台有一个随着我们项目启动就会启动的生产事件并广播事件的线程,前台会通国joinListen监听方法建立连接,监听事件,然后每隔一定时间就会发送一个refresh事件到后台,从而获得后台产生的消息。这也就是为什么我前面说pushlet表面是服务器推,但是实际上还是前台拉的原因。
接下来继续详细的看代码,那么上面说的第三和第四个请求是怎么发出去的,需要看我们的jsajax-pushlet-client.js,我们先在jsp上调用了iPL.init()方法。看看init方法都干了什么:
_init: function () { PL._showStatus(); PL._setStatus('initializing...'); /* Setup Cross-Browser XMLHttpRequest v1.2 Emulate Gecko 'XMLHttpRequest()' functionality in IE and Opera. Opera requires the Sun Java Runtime Environment <http://www.java.com/>. by Andrew Gregory http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/ This work is licensed under the Creative Commons Attribution License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.5/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. */ // IE support if (window.ActiveXObject && !window.XMLHttpRequest) { window.XMLHttpRequest = function() { var msxmls = new Array( 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'); for (var i = 0; i < msxmls.length; i++) { try { return new ActiveXObject(msxmls[i]); } catch (e) { } } return null; }; } // ActiveXObject emulation if (!window.ActiveXObject && window.XMLHttpRequest) { window.ActiveXObject = function(type) { switch (type.toLowerCase()) { case 'microsoft.xmlhttp': case 'msxml2.xmlhttp': case 'msxml2.xmlhttp.3.0': case 'msxml2.xmlhttp.4.0': case 'msxml2.xmlhttp.5.0': return new XMLHttpRequest(); } return null; }; } PL.pushletURL = PL._getWebRoot() + 'pushlet.srv'; PL._setStatus('initialized'); PL.state = PL.STATE_READY; },