DWR3.0框架入门(3) —— ScriptSession的维护及优化

1.ScriptSession使用中存在的问题

在上一节实现了服务器的推送功能,但是根据 ScriptSession的生命周期我们可以得出以下几点的问题:

(1)ScriptSession不会与HttpSession同时创建

当我们访问一个页面的时候,如果是第一次访问,就会创建一个新的HttpSession,之后再访问的时候,就会保持当前的Session,即使是刷新,也能保持当前的HttpSession。

但是,ScriptSession不同,第一次访问,会创建一个ScriptSession,但是,如果你刷新,就会创建一个新的ScriptSession.

(2)如何得到ScriptSession

在DWR中,我们可以通过WebContextFactory.get()来取得一个WebContext对象,进而通过WebContext的getScriptSession()取得ScriptSession对象。

但是要注意,在我们自定义的Servlet中,我们也可以通过WebContextFactory.get()来取得一个WebContext,但是这种方法却不能取得ScriptSession对象。因为,此WebContext对象其实不是通过DWR的上下文环境得到的,所以,就根本没有创建ScriptSession对象。

假设这种方式也能得到ScriptSession的话,那么我们实现“推”也就可以不局限在DWR的上下文环境中了,那么其灵活性就会大很多了。所以,这就是我们不能在Servlet中实现推的原因。

(3) 关于刷新就创建一个新的ScriptSession问题

在我们需要推送的页面中,如果你刷新一下,那么就提交一个Http的request,此时,如果是第一次,那么就会创建一个httpSession对象,同时,请求由DwrServlet来处理后,就会创建一个ScriptSession.这个ScriptSession会和你的request请求的URI绑定放在一个由ScriptSessionManager维护的Map里面(这里面其实是一个URI对应的Set,在Set里面放置的是URI绑定的所有ScriptSession)。

当你刷新的时候,同样的一个HttpSession,却会创建一个新的ScriptSession,然后绑定到对应的URI上。

(4)向所有的页面访问者推送
当我们想向所有的页面访问者推送的时候,我们只需要,取得所有的页面访问者,就可以“推”了。
如何取得所有的页面访问者?

DWR3.0可以通过

[java] view plain copy

  1. //得到所有ScriptSession
  2. Collection<ScriptSession> sessions = Browser.getTargetSessions();

DWR2.x可以通过

[java] view plain copy

  1. Collection pages = webContext.getScriptSessionsByPage("/yourPage.jsp");

通过此方法,就可以实现调用客户端的javascript函数,实现对客户端的操作。

(5) 在上面的推送中产生的问题
上面的方法已经可以实现向所有的访问者推送。但是问题是,在客户端,如果用户刷新一次或多次,那么,Collection里面可能就保存了很多的无用的ScriptSession,所以不仅仅会影响性能问题,更重要的是,可能就不能实现你想要的功能。

2.如何管理有效的ScriptSession

由于上面的问题,我们就需要自己管理ScriptSession。其实,有效地HttpSession,就是那个和当前的HttpSession匹配的ScriptSession。

所以,我们就可以自己维护一个Map,在这个Map里面,我们定义key就是HttpSession的Id,其值就是ScriptSession对象。

在每一次页面载入的时候,都去注册此ScriptSession,那么就会把新的ScriptSession绑定到httpSession上面了。

在DWR3.0中推出了 ScriptSessionListener用来监听ScriptSession的创建及销毁事件。我们可以使用该监听器来维护我们自己的Map。

在上一节的代码上修改Demo:

1.新建一个类实现 ScriptSessionListener接口

[java] view plain copy

  1. package sugar.dwr;
  2. import java.util.Collection;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import javax.servlet.http.HttpSession;
  6. import org.directwebremoting.ScriptSession;
  7. import org.directwebremoting.WebContext;
  8. import org.directwebremoting.WebContextFactory;
  9. import org.directwebremoting.event.ScriptSessionEvent;
  10. import org.directwebremoting.event.ScriptSessionListener;
  11. public class DWRScriptSessionListener implements ScriptSessionListener {
  12. //维护一个Map key为session的Id, value为ScriptSession对象
  13. public static final Map<String, ScriptSession> scriptSessionMap = new HashMap<String, ScriptSession>();
  14. /**
  15. * ScriptSession创建事件
  16. */
  17. public void sessionCreated(ScriptSessionEvent event) {
  18. WebContext webContext = WebContextFactory. get();
  19. HttpSession session = webContext.getSession();
  20. ScriptSession scriptSession = event.getSession();
  21. scriptSessionMap.put(session.getId(), scriptSession);     //添加scriptSession
  22. System. out.println( "session: " + session.getId() + " scriptSession: " + scriptSession.getId() + "is created!");
  23. }
  24. /**
  25. * ScriptSession销毁事件
  26. */
  27. public void sessionDestroyed(ScriptSessionEvent event) {
  28. WebContext webContext = WebContextFactory. get();
  29. HttpSession session = webContext.getSession();
  30. ScriptSession scriptSession = scriptSessionMap.remove(session.getId());  //移除scriptSession
  31. System. out.println( "session: " + session.getId() + " scriptSession: " + scriptSession.getId() + "is destroyed!");
  32. }
  33. /**
  34. * 获取所有ScriptSession
  35. */
  36. public static Collection<ScriptSession> getScriptSessions(){
  37. return scriptSessionMap.values();
  38. }
  39. }

2.新建一个类继承 DefaultScriptSessionManager,用来绑定 DWRScriptSessionListener

[java] view plain copy

  1. package sugar.dwr;
  2. import org.directwebremoting.impl.DefaultScriptSessionManager;
  3. public class DWRScriptSessionManager extends DefaultScriptSessionManager {
  4. public DWRScriptSessionManager(){
  5. //绑定一个ScriptSession增加销毁事件的监听器
  6. this.addScriptSessionListener( new DWRScriptSessionListener());
  7. System. out.println( "bind DWRScriptSessionListener");
  8. }
  9. }

3.在web.xml中将 DWRScriptSessionManager  配置在 dwr-invoker servlet中

[java] view plain copy

  1. <init-param>
  2. <param-name >org.directwebremoting.extend.ScriptSessionManager </param-name>
  3. <param-value >sugar.dwr.DWRScriptSessionManager </param-value>
  4. </init-param>

这样在服务器启动时即会绑定 ScriptSessionListener, ScriptSession在创建时会自动添加到我们维护的Map中

4.通过以下方法获取所有的 ScriptSession

[java] view plain copy

  1. //得到所有ScriptSession
  2. Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();

3.使用 ScriptSessionFilter过滤

如果我们不想要给所有的客户端 推送消息,只想给特定的客户端推送,那么我们可以使用 ScriptSessionFilter来实现。在filter中去判定session中的Attribute值是不是我们给定的。

1.使用以下方法推送消息

//执行推送
Browser.withAllSessionsFiltered(filter, run);    //注意这里调用了有filter功能的方法

2.通过参数可知我们需要一个 ScriptSessionFilter对象,此时send的方法改写成如下:

[java] view plain copy

  1. public void send(final String content){
  2. //过滤器
  3. ScriptSessionFilter filter = new ScriptSessionFilter() {
  4. public boolean match(ScriptSession scriptSession) {
  5. String tag = (String)scriptSession.getAttribute("tag" );
  6. System. out.println(tag);
  7. return "receiverTag" .equals(tag);
  8. }
  9. };
  10. Runnable run = new Runnable(){
  11. private ScriptBuffer script = new ScriptBuffer();
  12. public void run() {
  13. //设置要调用的 js及参数
  14. script.appendCall( "show", content);
  15. //得到所有ScriptSession
  16. Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
  17. //遍历每一个ScriptSession
  18. for (ScriptSession scriptSession : sessions){
  19. scriptSession.addScript( script);
  20. }
  21. }
  22. };
  23. //执行推送
  24. Browser. withAllSessionsFiltered(filter, run);    //注意这里调用了有filter功能的方法
  25. }

3.在打开jsp页面时需要在 ScriptSession 中注入设定的attribute,MessagePush中的方法

[java] view plain copy

  1. public void onPageLoad(final String tag){
  2. //获取当前的ScriptSession
  3. ScriptSession scriptSession = WebContextFactory.get().getScriptSession();
  4. scriptSession.setAttribute( "tag", tag);
  5. System. out.println( "setAttribute");
  6. }

4.在jsp中调用该方法

<script type= "text/javascript">
         //这个方法用来启动该页面的ReverseAjax功能
         dwr.engine.setActiveReverseAjax( true);
         //设置在页面关闭时,通知服务端销毁会话
         dwr.engine.setNotifyServerOnPageUnload( true);

         var tag = "receiverTag";    //自定义一个标签
         messagePush.onPageLoad(tag);

         //这个函数是提供给后台推送的时候 调用的
         function show(content){
             $( "#content").text(content);
         }
</script >

这样我们可以给不同客户端的jsp中导入不同的tag值,过滤推送的客户端

原文地址:http://blog.csdn.net/carefree31441/article/details/17225851

时间: 2024-10-25 03:45:52

DWR3.0框架入门(3) —— ScriptSession的维护及优化的相关文章

DWR3.0框架入门(1) —— 实现ajax

框架简介:DWR(Direct Web Remoting) 是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站.它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器里一样. 本Demo实现的基本功能: 点击jsp界面的按钮,通过DWR调用到服务器端的java代码,在控制台打印出jsp输入框中的值 Demo构建流程: 1.新建Web工程 2.导入jar包:commons-logging-x.x.x.jar

Asp.Net MVC4.0 从入门到精通与项目实战 (Petapoco框架、二维码自定义、Bootstrap视图)视频教程

Asp.Net MVC4.0 从入门到精通与项目实战 (Petapoco框架.二维码自定义.Bootstrap视图)视频教程下载    联系QQ:1026270010 Asp.Net MVC 简介      MVC模式是“Model-View-Controller”的缩写,中文翻译为“模式-视图-控制器”.MVC模式是于20世纪70年代在smaltalk80的GUI设计中被提出的.它包括3个部分:模型(Model).视图(View)和控制器(Controller).MVC模式至今已被广泛使用,A

饥荒MOD lua编程0基础入门

前言 原贴写于饥荒游戏贴吧,为了使文章针对性更强,将原文切割并精简.此贴主要为编程0基础的modder讲解一些编程的基础知识.至于说有关饥荒框架的介绍,则会放在另一篇文章里讲解. 编程0基础的人,要想学习制作MOD,难度是比较大的,因为缺乏一些基本的编程概念,只懂得复制别人的代码或者在它们的基础上稍加改变,遇到稍微复杂一点的代码,就束手无策了.对于MOD崩溃或错误,也几乎没办法自行处理.但我也不推荐先去学一门编程语言之后再来学习MOD代码,这是没有必要的.事实上饥荒MOD里用到的基本编程知识都比

mybatis框架入门

初识mybatis 对原生jdbc程序(单独使用jdbc开发)问题总结 mybatis框架原理 mybatis入门程序 用户的增删查改 mybatis开发dao两种方法 原始dao开发方法(程序需要编写dao接口和dao实现类) mybatis的mapper接口(相当于dao接口)代理开发方法 mybatis配置文件SqlMapConfig.xml mybatis核心 mybatis输入映射 mybatis输出映射 mybatis的动态sql 第二天 订单商品的数据分析 改机映射(一对一.一对多

Extjs5.0从入门到实战开发信息管理系统(Extjs基础、Extjs5新特性、Spring、Spring mvc、Mybatis)视频教程

Extjs5.0从入门到实战开发信息管理系统(Extjs基础.Extjs5新特性.Spring.Spring mvc.Mybatis)视频教程下载   联系QQ:1026270010 Extjs作为一款优秀的JS前端开发框架以其良好的架构.丰富的UI组件库.完善的文档和社区支持等诸多优点拥有广泛的市场应用空间,开发人员无需过多的关注HTML.CSS甚至各种常用JS算法,只需把精力放在业务逻辑上,利用各种组件的相互组合调用便可轻松而高效的开发出系统的前端页面. Extjs5在之前版本的基础上又推出

Shiro权限控制框架入门1:Shiro的认证流程以及基本概念介绍

前言:我在最开始学习Shiro这个框架时,在网上搜索到的一个介绍比较全面的教程是:<跟我学Shiro>系列教程.但是在我看了他写的前几篇文章后,我发现虽然他在这个系列教程中把shiro的一些特性介绍地非常全面详细,但是整个教程的叙述方式还是有很大缺陷的.文章与文章之间并没有很好地串联起来,每篇文章介绍的东西都过于分散了,如果是对shiro完全不了解的新手来看的话完全是一场噩梦.就像一个网友评价的这样: 看了看这个教程,看完之后都想放弃shiro了,完全看不懂,后来百度了很多别的资料才理解了sh

EJB3.0快速入门

1.首先介绍运行环境及相关的配置: EJB的运行环境: JAVAEE应用服务器包含Web容器和EJB容器,EJB3.0应用需要运行在EJB容器里. Tomcat目前只是Web容器,它不能运行EJB应用. Jboss作为最常用EJB容器,其自身所带Web服务器部分就是直接使用Tomcat(Jboss的默认端口也为:8080). 相关配置: 1.配置classpath:%JDK安装目录%/lib/dt.jar和tools.jar 2.JDK版本需要1.5以上. 3.为Jboss设置Jboss_HOM

yii2.0框架安装心得

yii2.0安装心得 能够搜索到这篇文章的朋友相信是对yii框架有兴趣的,但是我不得不吐槽的是,这个安装过程确实让人头疼,接下来就让大家见证一下这个纠结的过程 根据官网的说法,安装这个框架需要用到composer,没有办法拉,先去大概的了解一下这个composer吧 什么是composer 根据composer的官网,它是这样解释的:composer是php用来管理依赖关系的工具,搞的这么复杂,直接说就是一个比较智能的下载工具不就好了.比如说我的项目是依赖yii框架的,而yii是依赖于其他东西的

cocos2d-x 3.0的入门程序:helloworld

看过了这么多不同方向的应用,发现很多程序入门都是helloworldhelloworld是所有程序员的绝对初恋 先看一下程序的运行结果吧 然后就是他的工程代码 工程的目录有两个 Classes:程序中的类 AppDelegate.h/cpp:Cocos2d-x程序框架          AppMacros.h:所用到的宏,主要是设置分辩率及对应的资源目录                   HelloWorldScene.h/cpp:场景显示层 win32:WIN32程序所涉及的主函数 main