zoukankan      html  css  js  c++  java
  • dwr3.0中维护自定义ScriptsessionManager

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

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

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

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

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

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

    DWR3.0可以通过

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

    DWR2.x可以通过

    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接口

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

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

    1 import org.directwebremoting.impl.DefaultScriptSessionManager;
    2 
    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中

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

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

     *如果是使用Spirng MVC管理的,可以使用如下方法:

    web.xml

     1 !-- spring mvc -->
     2     <servlet>
     3         <servlet-name>springmvc</servlet-name>
     4         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     5         <init-param>
     6             <param-name>contextConfigLocation</param-name>
     7             <param-value></param-value>
     8         </init-param>
     9         <load-on-startup>1</load-on-startup>
    10     </servlet>
    11     <servlet-mapping>
    12         <servlet-name>springmvc</servlet-name>
    13         <url-pattern>/</url-pattern>
    14     </servlet-mapping>
    15     <servlet-mapping>
    16         <servlet-name>springmvc</servlet-name>
    17         <url-pattern>/dwr/*</url-pattern>
    18     </servlet-mapping>

    spring-MVC.xml

     1 <!-- 要求dwr在spring容器中检查拥有@RemoteProxy 和 @RemoteMethod注解的类。注意它不会去检查Spring容器之外的类。 --> 
     2     <dwr:annotation-config id="dwr" /> 
     3     <!-- 要求DWR将util.js和engine.js映射到dwrController   -->
     4     <dwr:url-mapping /> 
     5         <!-- 定义dwr   -->
     6     <dwr:controller id="dwrController" debug="true"> 
     7         <dwr:config-param name="activeReverseAjaxEnabled"
     8             value="true" />
     9         <dwr:config-param name="allowScriptTagRemoting" 
    10             value="true" /> 
    11         <dwr:config-param name="crossDomainSessionSecurity" 
    12             value="false" /> 
    13         <dwr:config-param name="Async" 
    14             value="false" /> 
    15         <dwr:config-param name="scriptSessionTimeout"
    16             value="1800000"/>
    17     </dwr:controller>

    DWRScriptSessionManager代码如下:

     1 @Service
     2 public class DWRScriptSessionManager extends DefaultScriptSessionManager {
     3      
     4     public DWRScriptSessionManager() {
     5  
     6         // 绑定一个ScriptSession增加销毁事件的监听器
     7         this.addScriptSessionListener(new DWRScriptSessionListener());
     8     }
     9  
    10 }

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

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

    3.使用
    ScriptSessionFilter过滤

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

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

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

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

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

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

    public void onPageLoad(final String tag){
            //获取当前的ScriptSession
            ScriptSession scriptSession = WebContextFactory.get().getScriptSession();
            scriptSession.setAttribute( "tag", tag);
    }

    4.在jsp中调用该方法

     1 <script type= "text/javascript">
     2          //这个方法用来启动该页面的ReverseAjax功能
     3          dwr.engine.setActiveReverseAjax( true);
     4          //设置在页面关闭时,通知服务端销毁会话
     5          dwr.engine.setNotifyServerOnPageUnload( true);
     6         
     7          var tag = "receiverTag";    //自定义一个标签
     8          messagePush.onPageLoad(tag);
     9         
    10          //这个函数是提供给后台推送的时候 调用的
    11          function show(content){ 
    12              $( "#content").text(content);
    13          }     
    14 </script >
  • 相关阅读:
    python 数据类型 基础第二天
    Python基础第一篇
    前言、入门程序、常量、变量
    win10打开移动热点让手机连接上网教程
    win10移动热点问题
    博客园快速美化
    Idea提示没有符号类错误解决
    mybatis复习01
    test
    d190305面试题01总结
  • 原文地址:https://www.cnblogs.com/bigbang92/p/dwr-ScriptSessionListener-ScriptSessionManager.html
Copyright © 2011-2022 走看看