实际项目中我们需要根据登录系统的用户的不同,推送接收不同的消息,我们知道pushlet向后台服务发送请求后会生成一个session,每个session都有随机的一个id,我们需要把这个id改成userid传给后台服务,然后服务根据userid做一些业务处理。
如何修改sessionid为userid呢?第一步:
打开js文件添加一个属性userId: null,
var PL = {
NV_P_FORMAT: 'p_format=xml-strict',
NV_P_MODE: 'p_mode=pull',
pushletURL: null,
webRoot: null,
sessionId: null,
STATE_ERROR: -2,
STATE_ABORT: -1,
STATE_NULL: 1,
STATE_READY: 2,
STATE_JOINED: 3,
STATE_LISTENING: 3,
state: 1,
userId: null,
然后找到我们之前说的可以自定义请求参数的那个方法_doRequest中加入:拼接上我们的userid
var url = PL.pushletURL + '?p_event=' + anEvent;
if (anEvent == 'join' || anEvent == 'join-listen') {
url = url + "&mySessionId=" + PL.mySessionId;
}
接着就是在我们的jsp页面上面给userid赋值:
PL.userId = "zhagnsan";
PL._init();
PL.joinListen(“msgNum”);
在页面刷新或者关闭的时候我们还需要去取消订阅:
var subscriptionId = null;//全局变量
window.onbeforeunload = onUnsubscribe;.//触发事件
// 页面关闭时,取消订阅
function onUnsubscribe() {
if (subscriptionId != null) {
PL.unsubscribe(subscriptionId);
}
}
// 监听后台返回的数据信息,更新页面
function onData(event) {
// 保存订阅编号,用于页面关闭时进行退订
subscriptionId = event.get('p_sid');
console.log(event.get("who") +" "+
event.get(PL.userId) +" "+ event.get("date"));
}
然后我们需要重写pushlet创建session的方法,加入我们的userId。新建类PushletSessionManager继承SessionManager:Session.create(anEvent.getField("userId", "visitor"));
package com.css.app.personalmsg.server;
import nl.justobjects.pushlet.core.Event;
import nl.justobjects.pushlet.core.Session;
import nl.justobjects.pushlet.core.SessionManager;
import nl.justobjects.pushlet.util.PushletException;
public class PushletSessionManager extends SessionManager {
@Override
public Session createSession(Event anEvent) throws PushletException {
//Event的getField方法的第二个参数为当传递参数中不存在第一个参数字段时默认使用的值。
return Session.create(anEvent.getField("userId", "visitor"));
}
}
然后在pushlet.properties中找到sessionmanager.class改为我们写的类的路径:
sessionmanager.class=com.css.app.personalmsg.server.PushletSessionManager
ok,接下来就在我们的处理事件的方法中处理这个userId了:
package com.css.app.personalmsg.server;
import nl.justobjects.pushlet.core.Event;
import nl.justobjects.pushlet.core.EventPullSource;
import nl.justobjects.pushlet.core.Session;
import nl.justobjects.pushlet.core.SessionManager;
import javax.servlet.http.HttpServlet;
import java.util.Date;
public class MySinglePlushlet extends HttpServlet {
private static final long serialVersionUID =1l;
//private static SystemService systemService;
static public class HwPlushlet extends EventPullSource {
// 休眠五秒 执行一次pullEvent
@Override
protected long getSleepTime() {
return 5000;
}
@SuppressWarnings("deprecation")
@Override
protected Event pullEvent() {
Event event = Event.createDataEvent("/msgNum");
Session[] sessions = SessionManager.getInstance().getSessions();
if(sessions.length > 0){
for(Session session : sessions){
if (session.getSubscriber().match(event) != null) {
try {
String userId = session.getId().split("_")[0];
// GetPersonalMsgService service = new GetPersonalMsgService(userId);
// int num = service.getmsg();
int num = 2;
event.setField(userId, num);
event.setField("who",userId);
event.setField("date",new Date().toString());
System.out.println(session.getId()+"执行中...");
} catch (Exception e) {
event.setField("mess", "异常错误!");
}
} else{
session.stop();
System.out.println(session.getId()+"已经取消订阅了=================================");
}
}
}else{
System.out.println("no pushlet session");
}
return event;
}
}
}
ok代码更改完毕,我们的思路是,系统的所有的用户都订阅相同的事件,没有一个用户订阅,就会有一个session生成,在后台遍历这个session拿到userId处理后,把结果通过event.setField(userId, num);放进去,然后前台在通过event.get(PL.userId)拿到各自的信息。
但是问题来了,我们发现我们现在使用的是单线程的,所以我们只能通过这种方式,把不同用户的处理结果都放在一个事件event中,如果用户大量的时候,根本是不科学的,因为单线程中,我们无法一个一个生成事件,否则就不会准确的按照我们设置的睡眠时间去“推”。效率也低。所以我们需要做成多线程的方式,为每个用户单独生成一个线程去处理,这样各个用户之间互相不受影响。下一篇继续使用多线程改进方案。