1、服务器向指定客户端推送数据
完成聊天室之类的项目时,利用DWR推模式向所有客户端推送数据,的确是很方便,只要客户端的访问页面确定就可以了。但是,若需要对访问同一页面的两个客户端(特别是根据用户身份作不同处理),加以区分,推送不同数据时,就没这么简单了。
有两种方式可以解决这个问题:
a)、服务端不处理,只管往客户端推送数据,由客户端对收到的数据进行过滤,然后再显示出来。但这种方式的缺点很明显,数据包多且不安全。
b)、对每个客户端进行单儿标识。DWR中以ScriptSession来代表一个客户端连接,我们可以通过设置ScriptSession的属性,来达到标识客户端的作用。如将sessionid或用户登录名保存在相应的ScriptSession属性中,向客户端推送数据时,根据这个属性加以过滤。相应的代码片段如下:
/**
* 返回有效的ScriptSession.
* @param user
* @return
*/
@SuppressWarnings("unchecked")
private ScriptSession getCurrentSession(String user){
ScriptSession xSession = null;
Collection<ScriptSession> sessions = new HashSet<ScriptSession>();
sessions.addAll(sctx.getScriptSessionsByPage(PAGE_MAIN));
for (ScriptSession session : sessions) {
//查询与消息接收者相符的客户端页面,并输出消息内容
String xuser = (String)session.getAttribute(SESSION_ATTRNAME_USER);
if(xuser != null && xuser .equals(user)){
xSession = session;
}
}
return xSession;
}
/**
* 清除已有连接, 标识当前连接用户(登录或刷新页面时,进行必要的清理).
* @param user
* @param session
*/
private void cleanDwrConnection(user,ScriptSession session){
String jid = StringUtils.parseBareAddress(user);
ScriptSession oldSession = getCurrentSession(jid);
if(oldSession != null && oldSession != session){
oldSession.invalidate();
oldSession = null;
}
session = WebContextFactory.get().getScriptSession();
session.setAttribute(SESSION_ATTRNAME_USER, jid);
}
2、使用DWR推模式的实现中,刷新页面引起长连接丢失问题
最近在做web版即时消息客户端时,遇到这样一个问题:为了减少无用的服务连接,只在登录后才激活长连接(dwr.engine.setActiveReverseAjax(true),注销后取消长连接)。登录客户端后,用了一段时间后,无法收消息了(消息无法推送到客户端)。后来调试后,发现ScriptSession实例没有绑定物理连接信息(conduits:m:root为空)。测试后发现,当刷新页面后,会产生一个新的ScriptSession实例,而这个ScriptSession的conduits:m:root为空,所以怎么都无法将数据推送到客户端去了。
客户端激活长连接后(dwr.engine.setActiveReverseAjax(true);),对应的ScriptSession实例会绑定物理连接信息,而刷新页面刷新而不重新激活长连接,新产生的ScriptSession是没有绑定物理连接信息的,一旦绑定物理连接信息的ScriptSession被销毁后,就产生了这个问题。
posted on 2008-03-31 16:41
josson 阅读(4116)
评论(0) 编辑 收藏 所属分类:
web开发