在使用过程中发现,推送页面向接收页面推送是,第一次可以实现,假如接受页面不刷新,则在DWR不存在问题,假如接受页面在推送过程中进行了刷新操作,则导致推送不成功。所以采用监听器的方式来实现对ScriptSession的创建和销毁。DWR3.0中推出了 ScriptSessionListener用来监听ScriptSession的创建及销毁事件。
public class DWRScriptSessionListener implements ScriptSessionListener{
//创建一个Map key为sessionId,value为scriptSession对象,用来维护ScriptSession
private static final Map<String,ScriptSession> scriptSessionMap = new HashMap<>();
/**
* @method sessionCreated
* @description 创建session
* @date: 2018/7/12 15:37
* @author: xuxianzhao
*
* @return
*/
@Override
public void sessionCreated(ScriptSessionEvent ev) {
WebContext webContext = WebContextFactory.get();
//获取httpsession
HttpSession session = webContext.getSession();
ScriptSession scriptSession = ev.getSession();
//推送页面的通过DWR进行访问时,将sessionID作为key放进Map中,则可以刷新页面也不会丢失
scriptSession
scriptSessionMap.put(session.getId(),scriptSession);
}
/**
* @method sessionDestroyed
* @description 销毁scriptSession
* @date: 2018/7/12 15:39
* @author: xuxianzhao
*
* @return
*/
@Override
public void sessionDestroyed(ScriptSessionEvent ev) {
WebContext webContext = WebContextFactory. get();
HttpSession session = webContext.getSession();
scriptSessionMap.remove(session.getId());
}
/**
* 获取所有ScriptSession
*/
public static Collection<ScriptSession> getScriptSessions(){
return scriptSessionMap.values();
}
}
通过一个类来管理监听器的创建
/*
创建一个监听器管理类
*/
public class DWRScriptSessionManager extends DefaultScriptSessionManager {
public DWRScriptSessionManager(){
//绑定一个ScriptSession增加销毁事件的监听器
this.addScriptSessionListener( new DWRScriptSessionListener());
}
将监听器管理类配置到web.xml中
<init-param>
<param-name >org.directwebremoting.extend.ScriptSessionManager</param-name>
<param-value >com.allcure.queue.dwr.DWRScriptSessionManager</param-value>
</init-param>
将推送方法的推送代码进行改造:
ScriptSessionFilter scriptSessionFilter = new ScriptSessionFilter() {
@Override
public boolean match(ScriptSession scriptSession) {
if (null == scriptSession.getAttribute("key")){
return false;
}else {
return scriptSession.getAttribute("key").equals(userSession.getMedicalRoomId());
}
}
};
Runnable run = new Runnable(){
private ScriptBuffer scriptBuffer = new ScriptBuffer();
@Override
public void run() {
scriptBuffer.appendCall("receiveMessages",true);
Collection<ScriptSession> scriptSessions = DWRScriptSessionListener.getScriptSessions();
for (ScriptSession scriptSession : scriptSessions){
scriptSession.addScript(scriptBuffer);
}
}
};
Browser.withAllSessionsFiltered(scriptSessionFilter,run);
即可完成。
附:DWR推送和webSocket实现服务器推送的对比
个人理解:如有错误,求轻喷,并求指教。
1. DWR推送就像海贼王里面的路飞,你想去拿一个东西,只要加长你的手臂就能拿到(后台可以调用前端js方法),而webSocket则像时使用某种工具,通过工具来传输。
2.兼容性,webSocket需要考虑浏览器兼容性的问题,当然基于chrome开发的浏览器均可以使用,火狐进行一些配置才可以使用。但是低版本的IE则不可以。由于业务需求我们公司C++组自己基于chrome内核开发了一个浏览器也是不能使用,但DWR可以使用。
3,个人觉得DWR不适合做实时聊天,做任务推送可以,因为DWR的API中并没有提到服务器宕机或者一方强制关闭链接后如何处理。webSocket则有相应的支持。