dwr实现javaweb实时聊天通讯网页版常见问题及解决方案
来源:互联网 发布:上汽集团 知乎 编辑:程序博客网 时间:2024/05/15 03:47
使用dwr实现javaweb实时聊天通讯网页版的时候可能会遇到以下问题:
1、因为每次刷新页面都创建一个scriptsession而产生发送一条消息接收方收到多条消息的问题;
问题分析:
scriptsession不同于普通的session,普通的session在我们第一次访问网站的时候创建,再次访问此网站不会再次创建session(session有效期内,且没有关闭浏览器或清除缓存),而scriptsession则是每打开一个页面或者刷新页面都会生成新的scriptsession,并且短时间内原有的scriptsession并没有销毁(有的文档上说的是5分钟),所以会同时存在多个scriptsession,一般的定向发送消息会使用Browser.withAllSessionsFiltered(ScriptSessionFilter filter, Runnable task)该方法,具体实现如下:
Browser.withAllSessionsFiltered(new ScriptSessionFilter() {
public boolean match(ScriptSession session) {
if (session.getAttribute("userId") == null)
return false;
else
return (sendtoId.indexOf((String)session.getAttribute("userId"))>=0);
}
}, new Runnable() {
private ScriptBuffer script = new ScriptBuffer();
public void run() {
Collection<ScriptSession> sessions = Browser.getTargetSessions();
for (ScriptSession scriptSession : sessions) {
script.appendCall("showTotalNum", totalUnCheckedNum);
scriptSession.addScript(script);
}
}
});
所以在存在多个scriptsession的情况下就回出现发送一条消息但是接收到多条消息的问题。
解决方案:
自己创建dwr监听类DWRScriptSessionListener.java,在初始化的时候使用自己的监听类,自己的监听类中定义Map来保存有效的scriptsession,定向发送消息时从此Map中获取scriptsession,完成发送,就能避免重复发送
DWRScriptSessionListener.java代码如下:
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.event.ScriptSessionEvent;
import org.directwebremoting.event.ScriptSessionListener;
import com.ches.bean.UnitRegister;
public class DWRScriptSessionListener implements ScriptSessionListener {
// 维护一个Map key为session的Id, value为ScriptSession对象
public static final Map<String, ScriptSession> scriptSessionMap = new HashMap<String, ScriptSession>();
/**
* ScriptSession创建事件
*/
@Override
public void sessionCreated(ScriptSessionEvent event) {
HttpSession session = WebContextFactory.get().getSession();
UnitRegister user = (UnitRegister) session.getAttribute("user");
ScriptSession scriptSession = event.getSession();
if(user!=null){
scriptSession.setAttribute("userId", user.getId());
scriptSessionMap.put(user.getId(), scriptSession); // 添加scriptSession
}else{
scriptSession.setAttribute("userId", session.getId());
scriptSessionMap.put(session.getId(), scriptSession); // 添加scriptSession
}
}
/**
* ScriptSession销毁事件
*/
@Override
public void sessionDestroyed(ScriptSessionEvent event) {
if(event.getSession() != null&&!event.getSession().isInvalidated()){
event.getSession().invalidate();
}
}
/**
* 获取所有ScriptSession
*/
public static Map<String, ScriptSession> getScriptSessions() {
return scriptSessionMap;
}
}
如何使用自己定义的监听类:
原始监听的代码为:
public void init() throws ServletException {
try {
Container container = ServerContextFactory.get().getContainer();
ScriptSessionManager manager = container.getBean(ScriptSessionManager.class);
ScriptSessionListener listener = new ScriptSessionListener() {
@Override
public void sessionCreated(ScriptSessionEvent event) {
HttpSession session = WebContextFactory.get().getSession();
UnitRegister user = (UnitRegister) session.getAttribute("user");
if(user!=null){
event.getSession().setAttribute("userId", user.getId());
}else{
event.getSession().setAttribute("userId", session.getId());
}
}
@Override
public void sessionDestroyed(ScriptSessionEvent arg0) {
}
};
manager.addScriptSessionListener(listener);
} catch (Exception e) {
e.printStackTrace();
}
}
使用自己的监听类则改为:
public void init() throws ServletException {
try {
Container container = ServerContextFactory.get().getContainer();
ScriptSessionManager manager = container.getBean(ScriptSessionManager.class);
ScriptSessionListener listener = new DWRScriptSessionListener();
manager.addScriptSessionListener(listener);
} catch (Exception e) {
e.printStackTrace();
}
}
发送信息处的代码处理为:
Browser.withAllSessionsFiltered(new ScriptSessionFilter() {
public boolean match(ScriptSession session) {
return true;
}
}, new Runnable() {
private ScriptBuffer script = new ScriptBuffer();
public void run() {
Map<String, ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
ScriptSession scriptSession = sessions.get(sendtoId);
if(scriptSession!=null){
script.appendCall("showMessage",totalUnCheckedNum , unCheckedNum, thisId, thisName, sendtoId, sendtoName, sendMessage);
scriptSession.addScript(script);
}
}
});
2、关闭聊天界面后无法收到消息
问题分析:
解决了问题1之后,按照以上的思路要想在其他页面显示和反馈收到的消息将无法实现,因为只给最后的保存在自定义的map中的scriptsession发送消息,就只能在打开的对话页面接收消息,关闭对话页面继续浏览其他页面则无法接收消息。
解决方案:
同时使用原始的发送消息策略和问题1中改造后的发送消息策略,即
(1)Browser.withAllSessionsFiltered(new ScriptSessionFilter() {
public boolean match(ScriptSession session) {
if (session.getAttribute("userId") == null)
return false;
else
return (sendtoId.indexOf((String)session.getAttribute("userId"))>=0);
}
}, new Runnable() {
private ScriptBuffer script = new ScriptBuffer();
public void run() {
Collection<ScriptSession> sessions = Browser.getTargetSessions();
for (ScriptSession scriptSession : sessions) {
script.appendCall("showTotalNum", totalUnCheckedNum);
scriptSession.addScript(script);
}
}
});
(2)Browser.withAllSessionsFiltered(new ScriptSessionFilter() {
public boolean match(ScriptSession session) {
return true;
}
}, new Runnable() {
private ScriptBuffer script = new ScriptBuffer();
public void run() {
Map<String, ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
ScriptSession scriptSession = sessions.get(sendtoId);
if(scriptSession!=null){
script.appendCall("showMessage",totalUnCheckedNum , unCheckedNum, thisId, thisName, sendtoId, sendtoName, sendMessage);
scriptSession.addScript(script);
}
}
});
说明:1、没有放在自定义map中的scriptsession在销毁之前一直存在的。
2、发送消息策略(1)和(2)中的回调函数名称要区分,不能使用同一名称。
- dwr实现javaweb实时聊天通讯网页版常见问题及解决方案
- DWR 逆ajax 实现网页聊天
- 网页版聊天解决方案
- WebSocket+多线程python socket网页版实时在线聊天实现
- js+php实现实时网页聊天功能
- 网页实时聊天之PHP实现websocket
- 网页实时聊天之PHP实现websocket
- NodeJS+Redis实现Web实时通讯聊天模块
- javascript和jQuery实现网页实时聊天的ajax长轮询
- JavaWeb网页版计算器实现
- 基于.Net平台开发的网页版实时聊天程序
- Dwr 实现消息实时传递
- DWR 实现数据实时刷新
- DWR实时自动动态更新网页数据
- websocket+ javaweb 实现浏览器聊天
- 网页版在线聊天java Socket实现
- AJAX+js实现实时聊天
- AJAX+js实现实时聊天
- Setting property 'source' to 'org.eclipse.jst.jee.server:XX did not find a mat的解决办法
- DefaultHttpClient过时的替换
- [日推荐]『识花草』做个辛勤的小园丁
- 2017-9-17pat甲级 B
- 码云 IntelliJ IDEA 插件 Intellij-GitOSC
- dwr实现javaweb实时聊天通讯网页版常见问题及解决方案
- 流媒体相关交互协议和开源服务介绍
- linux文件时间参数atime,ctime,mtime
- linux 中断irq_chip
- numpy中argsort函数用法
- Fresco强大的图片加载组件
- 机器学习损失函数、L1-L2正则化的前世今生
- 【ccf-201503-1】图像旋转
- 三点通信