来自RMI或者CORBA的服务器端回掉可以通知客户端服务器上有什么变化。但是如果客户端是浏览器,情况又如何呢?本文介绍pushlets来完成此功能。
下载:
http://www.pushlets.com ,当前下载版本为2.0.0
正文:
当前,开发者越来越将servlet或者jsp作为服务器前端语言了,但是同时,如果浏览器已经装载了当前html页面,它就很难从服务器端获取更新信息了。(如果客户端不主动请求的话)。
对于经验丰富的程序员,我们容易想起applet。本文我们要讨论一下到底如何做最好。
1, server-to-web client 通知:现有解决方案/font>
在进入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内容给客户端。如下:
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Pragma" content="no-cache">"+(i++)+"");
out.flush();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
out.print("
"+e+" ");
}
}
} catch (Exception e) {
out.print(""+e+" ");
}
%>
ä¸ä¸ä¸ªä¾åä¸ï¼æä»¬äºç»ä¸ä¸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
parent.push('";
/** End the line of JavaScript */
String jsFunPost = "') ";
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><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
/font>
WAIT...
è¿è¡ä¸ä¸ä¸é¢ç代ç ï¼å®ä½ç°äº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