转自:http://blog.csdn.net/houpengfei111/article/details/7498481
网络资源:
一、简述:
pushlet是一种comet实现,在servlet机制下,数据从server端的java对象直接推送(push)到(动态)HTML页面,而无需任何java applet或者插件的帮助。
二、使用pushlet需要做哪些准备工作
1.下载pushlet
http://sourceforge.net/projects/pushlets/files/pushlets/2.0.4/pushlet-2.0.4.zip/download
2.eclipse 或者myeclipse搭建简单项目
(1)创建工程
a. File à new à projectàweb project 项目名称为: pushlet-demo
(2)加依赖文件
a.在下载文件的webapps 演示文件夹中找寻文件
b.在src目录中添加 log4j.properties pushlet.properties sources.properties ,添加后修改sources.properties 清空演示配置,准备添加自己的配置
source1=nl.justobjects.pushlet.test.TestEventPullSources$TemperatureEventPullSource
source2=nl.justobjects.pushlet.test.TestEventPullSources$SystemStatusEventPullSource
source3=nl.justobjects.pushlet.test.TestEventPullSources$PushletStatusEventPullSource
source4=nl.justobjects.pushlet.test.TestEventPullSources$AEXStocksEventPullSource
source5=nl.justobjects.pushlet.test.TestEventPullSources$WebPresentationEventPullSource
source6=nl.justobjects.pushlet.test.TestEventPullSources$PingEventPullSource
注意:可以不清空,以上斜体部分在sources.properties注释掉即可。
c.添加依赖jar包
在下载文件的lib目录下复制 pushlet.jar pushletclient.jar导入到自己工程的/WEB-INF/lib
d.配置web.xml
<servlet>
<servlet-name>pushlet</servlet-name> <servlet-class>nl.justobjects.pushlet.servlet.Pushlet</servlet-class>
注意:此处名字太长如果记不住可以利用eclipse等工具随便下个类中用快捷键提示得到。
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>pushlet</servlet-name>
<url-pattern>/pushlet.srv</url-pattern>
注意:此处默认为/pushlet.srv,一般无需改动,要想改动需要在对应的js文件。
</servlet-mapping>
(3)添加实例
a. 创建数据源
package com.source;
import java.io.Serializable;
import nl.justobjects.pushlet.core.Event;
import nl.justobjects.pushlet.core.EventPullSource;
publicclass HelloWorldEventPullSource implements Serializable{
privatestaticfinallongserialVersionUID = 1L;
staticpublicclass HelloWorldEvent extends EventPullSource{
@Override
protectedlong getSleepTime() {
return 1000; //刷新时间
}
@Override
protected Event pullEvent() {
Event event =Event.createDataEvent("/source/event");//事件标识
注意:此处”/source/event”将对应页面js代码中的PjoinListen中的参数
event.setField("msg", "hello,world");//封装参数
return event;
}
}
}
b. 配置数据源
sources.properties 进行数据源配置
添加source1=com.source.HelloWorldEventPullSource$HelloWorldEvent
注意: HelloWorldEventPullSourc这是类名,HelloWorldEvent是内部类名。
c. 页面调用
Index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>index.html</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="js/ajax-pushlet-client.js"></script>
<!—js 从演示项目的 lib 下copy -->
<script type="text/javascript">
PL._init();
PL.joinListen('/source/event'); //事件标识 在数据源中引用
function onData(event) {
alert(event.get("msg"));
}
</script>
</head>
<body>
</body>
</html>
4. 测试 http://localhost:8080/pushlet-demo/index.html
三、对pushlet的一点看法:
个人认为pushlet后台代码核心主要在事件源,所以我们自己创建一个事件源类,这个事件源类必须实现EventSource或者继承EventPullSource类。如果事件源类实现了EventSourc。接口,那么它需要实现把事件”推”到pushlet框架的方法;如果事件源类扩展了EventPullSource类,那么Pushlet框架会每隔一段时间自动地拉取事件源产生的事件。然后,把事件源类捆绑到TestEventPullSources类中,最后将这个事件源的类名存放到类路径下的资源文件sources.properties中。将事件源捆绑到TestEventPullSources类中,并存放于资源文件中,目的是便于对事件源的创建和管理。当Pushlet.服务器被载人时,事件源管理器就会在类路径中寻找资源文件,并将文件中的事件源载人激活。
一个简单的做法,当我们继承了EventPullSource类(只能继承的原因是该类是个抽象类),主要实现两个方法,一个就是getSleepTime()和pullEvent(),其中getSleepTime是为了控制刷新数据的时间,而在pullEvent是写自己业务代码的地方。写完这个类后,除了要在jsp页面完成一些代码外,更主要的是要在sources.properties文件进行相关的配置。(详见第二点)显而易见,这种做法虽然理解起来简单但是不便于扩展,配置起来也有一定的麻烦。
经过研究源码,查找API,发现EventPullSource这个类除了上面提到的方法外,还有activate()、isAlive()、passivate()、run()、start()、stop()仔细研究发现其实EventPullSource是实现了EventSource及runnable这两个接口的。既然这样,可以想到自己是否也可以写一个类实现这两个接口,将自己的业务方法封装在pullEvent方法中,并在Jsp页面中的javaScript中编写一些必须的方法,发现可以达到推送的目的。然而这样不需要在sources.properties中进行相关配置,省去了很多麻烦。
说的再多不如给一段代码来的直观点:
package com.unistrong.dial.pushlet;
import java.util.HashMap;
import java.util.Map;
import com.unistrong.dial.vo.Dial;
import nl.justobjects.pushlet.core.Dispatcher;
import nl.justobjects.pushlet.core.Event;
import nl.justobjects.pushlet.core.EventSource;
import nl.justobjects.pushlet.util.Log;
public class ServerMain implements EventSource,Runnable {
private volatile boolean alive = false;
private volatile boolean active = false;
private static int threadNum = 0;
private Thread thread;
private long sleepTime=0;
private String eventName;
private Map<String, String> map=new HashMap<String, String>();//同一个id的事件只能在集合中出现一次
public ServerMain() {
}
public ServerMain(long sleepTime,String eventName,Map<String, String> map) {
this.sleepTime=sleepTime;
this.eventName=eventName;
this.map=map;
}
public Event pullEvent(){
Dial dial=new Dial();
dial.setDid("123");
dial.setData("10000");
dial.setDname("dial");
Event event = Event.createDataEvent(eventName);
event.setField("did", dial.getDid());
//event.setField("data", dial.getData());
//event.setField("dname", dial.getDname());
return event;
}
public void start() {
thread = new Thread(this, "EventPullSource-" + (++threadNum));
thread.setDaemon(true);
thread.start();
}
public boolean isAlive() {
return alive;
}
/**
* Stop the event generator thread.----->停止事件构造器线程
*/
public void stop() {
alive = false;
if (thread != null) {
thread.interrupt();
thread = null;
}
}
/**
* Activate the event generator thread.------->激活事件构造器线程。
*/
synchronized public void activate() {
if (active) {
return;
}
active = true;
if (!alive) {
start();
return;
}
Log.debug(getClass().getName() + ": notifying...");
notifyAll();
}
/**
* Deactivate the event generator thread.--------->停用事件构造其线程。
*/
public void passivate() {
if (!active) {
return;
}
active = false;
}
/**
* Main loop: sleep, generate event and publish.----->主循环:设置睡眠,事件构造器和进行发布
*/
public void run() {
Log.debug(getClass().getName() + ": starting...");
alive = true;
while (alive) {
try {
Thread.sleep(sleepTime);
// 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...
/*直到我们得到通知才能不在等待,如果没有用户订阅我们要消耗cpu来维持活动*/
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");
}
}
在这段代码中我们主要注意以下几个方面即可:
1.个人认为根据自己的业务的实际情况可以增加一些属性,并且要生成一无参和有参数的构造方法。有参数的构造方法的参数根据实际情况而定,当然上面代码中的参数我认为是几个必要的参数,其他视情况而定。
2.主要的业务代码仍然在pullEvent方法中实现。
3.除了pullEvent这个方法自己写之外,其他方法完全可以复制EventPullSource里面的代码,省力又准确。
4.写好这个类,我们就可以在struts框架的Action中,或者servlet中直接调用其中的activate()方法。当然如果再考虑严谨点我们多写一个类当做业务层来调用里面的方法,不仅可以推送数据,也可以停用单个或者所有的event.
再贴段代码看看就会明白:
package com.unistrong.dial.pushlet;
import java.util.HashMap;
import java.util.Map;
public class EventManager {
private static EventManager em=new EventManager();
public EventManager() {
}
public static EventManager getInstance(){
return em;
}
//eventList集合主要用来放所有的事件,为了防止重复所以使用map集合
private Map<String, ServerMain> eventList=new HashMap<String, ServerMain>();
public Map<String, ServerMain> getEventList() {
return eventList;
}
/**
* 创建订阅
*/
public void createEvent(long sleepTime,String eventName,Map<String, String> map){
System.out.println("开启订阅:"+eventName);
ServerMain sm=new ServerMain(sleepTime,eventName,map);
eventList.put(eventName, sm);
sm.activate();
}
/**
* 停止订阅
*/
public void removeEvent(String eventName){
if(eventList.containsKey(eventName)){
System.out.println("停用:"+eventName);
ServerMain sm=new ServerMain();
sm.stop();
eventList.remove(eventName);
}
}
}
这样看起来就专业多,也严谨的多。
最后,在jsp页面的javaScript中应该注意的几个方面:
首先,不论你在后台是继承EventPullSource方法还是实现EventSource接口,都要在
Jsp页面的<head>标签里引入ajax-pushlet-client.js文件。
【关于继承EventPullSource:】
在javaScript中写入以下代码并部署工程运行即可。
<script type="text/javascript">
PL._init();
PL.joinListen('/source/event'); //事件标识 在数据源中引用
function onData(event) {
alert(event.get("msg"));
}
</script>
【关于实现EventSource接口:】
在javaScript中写入以下代码:
<script type="text/javascript">
PL.setDebug(false);
function onEvent(event){
var did=event.get("did");
alert(did);
var data=event.get("data");
var dname=event.get("dname");
document.getElementById("chartdiv").innerHTML=did;
}
function listen(){
PL.joinListen("/${id}");<!—这里监听的id是要唯一标识的,可以由后台传过来-->
}
function leave(){
PL.leave();
}
</script>
查看js源码就可以看到这几个方法的作用,不过要注意的是我们要在页面的onload事件中调用其中的方法。如下:
<body onload="listen();return false;" onunload="leave();return false;">
………
</body>
如此运行就可以看到自己想要的效果。
以上是我自己在学习pushlet中的一些总结,当然里面有很大一部分是来自网络的支持,也有自己的看法,倘若有不正确之处,可以随时指正,这样我们可以共同进步。
pushlet笔记 3种发布方式
1.2.1. Direct Publishing (local)
1.2.1. Direct Publishing (local)
Your application may directly publish Events by using/src/nl/justobjects/pushlet/core/Dispatcher.getInstance().java . Since Dispatcher is (currently) a Singleton, sending the Event is a matter of callingDispatcher.getInstance().multicast()/unicast()/broadcast() .
The other two methods (EventSource and Pushlet protocol) will eventually callDispatcher.getInstance().multicast()/unicast()/broadcast() .
Note that in order to call Dispatcher.getInstance().multicast()/unicast()/broadcast() , your class needs to be in the same classloader as the Dispatcher.getInstance(). This may be an issue when for example your sender is in another web application. You may use the Pushlet protocol in that case or put pushlet.jar on the system CLASSPATH. In Tomcat you can also make pushlet.jar a shared library.
直接用Dispatcher的方法发布,可以向所有人广播,发布给订阅者,指定sessionid发布
1.2.2. Using EventSource
An EventSource is an object that is managed (activated/passivated) by the Pushlet framework. Developing your own EventSource involves creating a class that implements nl.justobjects.pushlet.core.EventSource(when your EventSource pushes Events to the framework) or that extendsnl.justobjects.pushlet.core.EventPullSource (when the framework should pull your EventSource at dedicated intervals) and adding your EventSource to a properties file aptly namedsources.properties .
See /webapps/pushlet/WEB-INF/classes/sources.properties for an example. This file specifies which EventSource objects need to be created and managed. Note: since v2.0.3 sources.properties can also be placed under WEB-INF. See /src/nl/justobjects/pushlet/core/EventSourceManager.java how this is done. See examples in /src/nl/justobjects/pushlet/test/TestEventPullSources where several example sources are bundled.
During initialization the EventSourceManager will look for the file sources.properties in the CLASSPATH. Usually this file will be put under WEB-INF/classes.
一个自己写的事件源类,需要配置在sources.properties ,要继承EventPullSource 或实现EventSource
1.2.3. Using the Pushlet protocol
The Chat and WebPresentation examples use the remote publication of events through the Pushlet (control) protocol. In a webapp the Pushlet JS API provides a p_publish() method through which your app may send events.
The /src/nl/justobjects/pushlet/test/PushletPingApplication.java provides a complete example illustrating sending and receiving Events and using/src/nl/justobjects/pushlet/client/PushletClient.java . DHTML clients may use the JavaScript pushlet library.
使用pushlet 协议 收发交互 , 可以跨服务器
Ajax-pushlet-client是pushlet的ajax客户端方式,对该JS进行分析后发现,它是采用了面向对象的javascript技术和充分利用XMLHttpRequest对象来实现的HTTP长连接,达到了服务器“推”技术。
1、属性
NV_P_FORMAT: 'p_format=xml-strict',//数据格式,默认是严格严格XML
NV_P_MODE: 'p_mode=pull', //pushlet采用的模式,默认为pull模式
pushletURL: null,//请求URL地址
webRoot: null,//项目根路径
sessionId: null,//sessionId
STATE_ERROR: -2,//一些状态常量
STATE_ABORT: -1,
STATE_NULL: 1,
STATE_READY: 2,
STATE_JOINED: 3,
STATE_LISTENING: 3,
state: 1,//状态
statusMsg: 'null', //状态消息
statusChanged: false,//状态是否发生了改变
statusChar: '|',//状态分隔符
2、方法
_init:获取XMLHttpRequest对象
设定pushlet的请求URL
将状态置为STATE_READY.
_doRequest (anEvent, aQuery):首先判断是不是出现错误,然后再判断是否需要等待状态,若不需要等待则构建查询字符串。最后调用_getXML(url, PL._onResponse)方法向服务器发出请求,后一个参数为回调方法。
_getWebRoot:获取项目根目录,可以根据实际项目修改
_getXML:以get方式请求URL,用同步或者异步方式
_onResponse(xml):先将xml转变为pushlet事件对象(_rsp2Events),得到多个PushletEvent对象,再调用_onEvent()处理每个事件。
_rsp2Events(xml):取得事件标签(event),然后调用PushletEvent(),可能得到多个PushletEvent对象。
_onEvent(event):处理由服务器端传来的事件,首先判断事件类型,由不同的类型调用不同的处理方法:
Data:调用_doCallback(event, window.onData),方法处理。onData是自定义;
Refresh:从event中取得刷新时间,然后调用_doRequest('refresh')刷新;
Error:将state置为STATE_ERROR,获取错误原因,调用_doCallback(event, window.onError);
join-ack:将状态置为” STATE_JOINED”,取得sessionId,调用_doCallback(event, window.onJoinAck);
join-listen-ack:将state设为STATE_LISTENING,取得sessionId,调用_doCallback(event, window.onJoinListenAck);
listen-ack、hb、hb-ack、leave-ack、refresh-ack、subscribe-ack、unsubscribe-ack、abort、/nack$/等类型也类似。
_addEvent(elm, evType, callback, useCapture):取得elm对象,调用以下三者之一:
obj.addEventListener(evType, callback, useCapture);
obj.attachEvent('on' + evType, callback);
obj['on' + evType] = callback。
当ajax-pushlet-client.js初始化时调用了该方法:PL._addEvent(window, 'load', PL._init, false);即初始化时相当于:window.onload=PL._init();
_doCallback(event,cbFunction):如果指定了回调方法,则调用cbFunction(event),如果没有指定那么调用window.onEvent(event)。
_getObject(obj):获取对象引用,若参数为对象直接返回该对象引用,若为字符串则按ID取得该对象。
PushletEvent(XML):与nl.justobjects.pushlet.Event相对应。其内部方法或属性如下:
Arr:数组,用于存放链值对;
getSubject():取得p_subject标签值;
getEvent():取得p_event标签值;
put(name, value);将链值对放入arr中;
get(name):按链取得值;
toString:转换为链值对字符串;
toTable:转换为表格;
将传入xml解析到arr中。
其对外公开方法:
heartbeat():实质是调用了PL._doRequest('hb'),向后台请求“hb”事件。再被封装成了:p_heartbeat()精简方式。
相似的方法还有:
Join:_doRequest('join', PL.NV_P_FORMAT + '&' + PL.NV_P_MODE);
joinListen:PL._doRequest('join-listen', query);请求加入同时监听;
leave:_doRequest('leave');
listen(aSubject):_doRequest('listen', query);按主题监听;
publish(aSubject, theQueryArgs):_doRequest('publish', query);按主题发布;
subscribe(aSubject, aLabel):_doRequest('subscribe', query);按主题订阅;
unsubscribe(aSubscriptionId):_doRequest('unsubscribe', query);按订阅ID退订;
pushlet:为一个servlet拦截订阅请求,调用EventSourceManager激活配置文件sources.properties中的所有事件源。
EventSourceManager: 事件源管理器,加载sources.properties配置文件,读取事件类加入到一个verctor中,还包含事件的activate、passivate、stop方法。
EventPullSource: 为一线程类,用于被用户继承,包含两个抽象方法getSleepTime()和pullEvent(),前者返回线程睡眠时间,后者返回事件。线程启动后循环睡眠然后针对事件发送多播。Dispatcher.getInstance().multicast(event);
command命令类: 用于封装参数session,event,request,response
constroller: doPushlish doJoin doLeave doRefresh等一些主要的操作方法。
相关推荐
本篇内容主要围绕"Pushlet学习(二) -- Pushlet CookBook部分翻译 + 注释"进行展开,将对Pushlet的工作原理、核心组件以及如何使用Pushlet进行编程进行深入讲解。 1. Pushlet简介: Pushlet是基于HTTP的 Comet 模式...
- **Pushlet CookBook**:《Pushlet学习(二) -- Pushlet CookBook部分翻译 + 注释.htm》可能是对Pushlet使用手册的中文译文,包含了一些基础用法和实例,注释提供了更直观的理解,帮助开发者快速上手。 3. **发布...
"pushlet.jar 和示例工程"是一个专注于实现服务器端向客户端主动推送消息的框架,它在Web开发领域中扮演着重要角色。...而提供的压缩包资源则为学习和实践Pushlet提供了便利,是深入研究和应用这一框架的重要资料。
【Pushlet服务器推技术】是一种实时通信技术,主要用于构建...在压缩包文件“pushlet”中,可能包含了实现Pushlet技术的源代码、配置文件和示例应用,供开发者学习和参考,以便在自己的项目中集成和使用Pushlet服务。
在IT行业中,Pushlet是一种基于Java的推送技术,主要用于实现实时的数据传输,尤其是在Web应用中创建...通过学习和实践"pushlet实现简单的用户聊天",开发者可以掌握这种技术,并将其应用于各种复杂的实时交互应用中。
使用这个实例,开发者可以学习如何设置PushLet服务器,创建推送通道,以及在客户端处理推送的消息。这对于学习和实践实时Web技术非常有帮助。同时,由于这是一个可以直接运行的实例,开发者可以快速验证概念,进行...
通过这个小例子,你可以直观地了解Pushlet框架的工作流程,并学习如何在自己的项目中集成和使用Pushlet。 **总结** Pushlet框架为Java开发者提供了一种实现服务器到客户端实时数据推送的有效工具,通过克服HTTP的...
**PUSHLET即时通讯工程实例详解** PUSHLET是一种基于Java技术实现的即时通讯系统,它允许服务器主动向客户端推送数据,而无需客户端持续轮询请求。...这个实例对于学习Java Web开发和理解PUSH技术有很好的实践价值。
综上所述,这些资源为学习和使用Pushlet提供了全面的支持,包括理论介绍、源码分析、实践示例和测试材料。对于想要深入理解和应用Comet技术,尤其是使用Java实现服务器推送的开发者而言,这些都是非常宝贵的参考资料...
通过上述知识点的学习和实践,你可以掌握如何使用Pushlet实现高效的点对点消息传递,这对于开发实时协作工具、在线游戏、聊天应用或者任何需要实时数据更新的系统都非常有用。在提供的"mypushlet"文件中,可能包含了...
"Pushlet-UserUnicast" 是一个专门针对特定用户进行推送技术演示的项目,它为初学者提供了深入了解和学习推送技术的良好平台。Pushlet是一种基于Java的实时数据推送框架,它允许服务器主动向客户端发送数据,而不是...
通过研究和运行这个demo,开发者可以学习到如何在Java环境中实现服务器推送,理解长连接的工作原理,以及如何处理轮询和非轮询的推送策略。这对于开发实时Web应用,特别是那些需要即时数据更新的场景,是非常有价值...
通过这个Demo,你可以学习到Pushlet的基本用法,理解服务器推送的实现机制,并为自己的实时Web应用打下基础。然而,Pushlet是较早的推送技术,现在已经有更多先进的解决方案,如WebSocket、Server-Sent Events (SSE)...
【服务器推送技术——PushLet应用详解<一>】 在当今的互联网应用中,实时性成为了不可或缺的需求,...通过学习和应用PushLet,开发者可以快速构建出具有实时功能的Web应用,提升用户体验,满足现代互联网应用的需求。
通过学习和运行这个示例,你可以更好地理解Pushlet的工作机制,并能将其应用于自己的项目中,实现服务器定时向页面推送消息的功能。在实际使用时,还可以根据需求进行定制和优化,例如,添加错误处理和日志记录,...
pushlet源码demo,提供有需要的同学学习,如有更好的实现或建议,欢迎提出
【推送技术】 推送技术是Web开发中的一种高级机制,它允许服务器主动向...通过这个例子,开发者可以学习到如何构建和部署一个能够进行服务器端数据推送的Web应用,这对于需要实时交互的系统设计具有重要参考价值。
通过学习和运行示例,可以掌握如何创建推送订阅、发布消息、以及如何在J2ME和JAVA WEB环境中集成Pushlet。 六、社区支持与文档 作为一个开源项目,Pushlet拥有活跃的开发者社区,提供了详细的文档和示例,用户可以...
标题中的“pushlet”是指Pushlet,一种基于Comet技术的服务器推送机制。...在“pushlet_向在线的特定...通过研究提供的源码和工具,开发者可以学习如何构建一个简单的实时消息推送系统,特别是针对特定在线用户的推送。
- `src`目录:可能包含示例代码的源文件,便于学习和修改。 通过研究和实践这些示例,开发者可以了解如何在自己的项目中实现服务器推送功能,提高应用程序的实时性和交互性。在实际开发中,需要注意网络连接的管理...