Pushlets:从Servlet发送消息给DHTML客户端浏览器
来自RMI或者CORBA的服务器端回掉可以通知客户端服务器上有什么变化。但是如果客户端是浏览器,情况又如何呢?本文介绍pushlets来完成此功能。
?
?
下载:
http://www.pushlets.com?,当前下载版本为2.0.0
?
?
?
?
?
?
正文:
?
?
当前,开发者越来越将servlet或者jsp作为服务器前端语言了,但是同时,如果浏览器已经装载了当前html页面,它就很难从服务器端获取更新信息了。(如果客户端不主动请求的话)。
对于经验丰富的程序员,我们容易想起applet。本文我们要讨论一下到底如何做最好。
?
?
1,??server-to-web client?通知:现有解决方案
?
?
在进入pushlet概念之前,让我们回顾一下现有的server-to-web client方案,可以归结为:HTML刷新、server-side callback以及messaging。
?
?
HTML refresh
?
?
<META HTTP-EQUIV="Refresh" CONTENT="4;URL=http://www.justobjects.nl">
?
?
页面会定时刷新,但是多少时间合适?
?
?
Server-side callback
?
?
在server-side callback中,server对象回调一个java-applet,通过RMI或者CORBA。通常,客户端首先传递一个RMI远程引用或者CORBA对象给server,server保存这些引用并按照顺序通知客户端,在javaworld的另外一篇文章中对此有详细的讨论(http://www.javaworld.com/javaworld/javaqa/1999-04/05-rmicallback.html)。
?
?
Messaging
?
?
消息方式的话,applet是messageing server的客户端,它通过TCP/IP连接或者UDP发送消息,最新进展甚至可以通过multicast。你可以通过消息中间件,如SoftWired的iBus,IBM的MQSeries,BEA的消息中间件等。JMS是消息的重要标准。
?
?
上述方案都有各自的优点和缺点。让我们看看Pushlet吧。
?
?
Pushlet是一个轻量级的客户端方案,不需要applet或者插件,直接和脚本以及HTML整合,使用标准HTTP连接,可以在任何servlet服务器中部署。它并一定是上述方案的替代,是你另外一个可选的方案。
?
?
Pushlet?基础
?
?
HTTP streaming
Pushlet基于HTTP streaming,它不是读取完html页面就关闭HTTP连接,连接仍然开放。
?
?
我们可以开发一个JSP或者servlet,它持续发送HTML内容给客户端。如下:
<HTML>
<HEAD>
???<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
???<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
</HEAD>
<BODY BGCOLOR="blue" TEXT="white">
<%
??int i = 1;
?
?
??try {
????while (true) {
???????out.print("<h1>"+(i++)+"</h1>");
???????out.flush();
?
?
???????try {
????????????Thread.sleep(3000);
???????} catch (InterruptedException e) {
???????out.print("<h1>"+e+"</h1>");
????????}
?????}
???} catch (Exception e) {
???????out.print("<h1>"+e+"</h1>");
???}
%>
</BODY>
</HTML>
?
?
?
?
下一个例子中,我们了结一下pushlet的机制。如何让页面3秒钟刷新一次?包含三个文件:push-js-stream.html,push-js-stram-pusher.jsp,push-js-stream-display.html。主页面是push-js-stream.html。
?push-js-stram-pusher.jsp
<%
???/** Start a line of JavaScript with a function call to parent frame. */
???String jsFunPre = "<script language=JavaScript >parent.push('";
?
?
???/** End the line of JavaScript */
???String jsFunPost = "')</script> ";
?
?
???int i = 1;
???try {
?
?
?????// Every three seconds a line of JavaScript is pushed to the client
?????while (true) {
?
?
????????// Push a line of JavaScript to the client
????????out.print(jsFunPre+"Page "+(i++)+jsFunPost);
????????out.flush();
?
?
????????// Sleep three secs
????????try {
?????????????Thread.sleep(3000);
????????} catch (InterruptedException e) {
?????????????// Let client display exception
?????????????out.print(jsFunPre+"InterruptedException: "+e+jsFunPost);
????????}
??????}
????} catch (Exception e) {
?????????????// Let client display exception
?????????????out.print(jsFunPre+"Exception: "+e+jsFunPost);
????}
?%>
Push-js-stram.html
<script LANGUAGE="JavaScript">
var pageStart="<HTML><HEAD></HEAD><BODY BGCOLOR=blue TEXT=white><H2>Server pushes: <P>";
var pageEnd="</H2></BODY></HTML>";
?
?
??// Callback function with message from server.
??// This function is called from within the hidden JSP pushlet frame
??function push(content) {
?
?
????// Refresh the display frame with the content received
????window.frames['displayFrame'].document.writeln(pageStart+content+pageEnd);
????window.frames['displayFrame'].document.close();
??}
?
?
</script>
</HEAD>
?
?
<FRAMESET BORDER=0 COLS="*,0">
?????<!-- frame to display the content pushed by the pushlet -->
?????<FRAME SRC="push-js-stream-display.html" NAME="displayFrame"?BORDER=0??SCROLLING=no>
?
?
?????<!-- Hidden frame with the pushlet that pushes lines of JavaScript-->
?????<FRAME SRC="push-js-stream-pusher.jsp" NAME="pushletFrame" BORDER=0?SCROLLING=no>
</FRAMESET>
?
?
Push-js-display.html
<HTML>
<BODY BGCOLOR=black TEXT=white>
<H1>WAIT...</H1>
</BODY>
</HTML>
?
?
运行一下上面的代码,它体现了pushlet的全部思想:在servlet或者jsp中将Javascript代码以流的形式传递给一个隐藏的frame。
?
?
?
?
Design of the Framework
?
?
Pushlet框架应用的基本模式是Publish-Subscribe模式,也称作Observer模式,有服务器端组件和客户端组件:
?
?
l?????????服务器端Java类(围绕pushlet.java),请看UML类图。
l?????????客户端可复用脚本(pushlet.js)和html(pushlet.html),用来接收DHTML客户端的事件。
(石头注:在2.0.0版本中,应该是lib目录下的js-pushlet-client.jsp和js-pushlet-net.html)
l?????????客户端java类(JavaPushletClient.java和JavaPushletClientListener.java)用来接收Java客户端的事件。
l?????????用来在DHTML layer中显示内容的layer.js、layer-grid.js、layer-region.js。
l?????????测试事件和例子应用(如EventGenerators.java和temperature.html)。
?
?
?
关键类是Pushlet这个servlet,Publisher类,Subscriber接口和Event类。客户端通过调用Pushlet servlet,客户端接收Event