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

    2.新建一个类继承 DefaultScriptSessionManager,用来绑定 DWRScriptSessionListener
    [java] view plain copy
     
    1. package sugar.dwr;  
    2.   
    3. import org.directwebremoting.impl.DefaultScriptSessionManager;  
    4.   
    5. public class DWRScriptSessionManager extends DefaultScriptSessionManager {  
    6.      public DWRScriptSessionManager(){  
    7.             //绑定一个ScriptSession增加销毁事件的监听器  
    8.             this.addScriptSessionListener( new DWRScriptSessionListener());  
    9.            System. out.println( "bind DWRScriptSessionListener");  
    10.      }  
    11. }  

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


    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

  • 相关阅读:
    48. Rotate Image
    47. Permutations II
    46. Permutations
    45. Jump Game II
    44. Wildcard Matching
    43. Multiply Strings
    42. Trapping Rain Water
    41. First Missing Positive
    40. Combination Sum II
    39. Combination Sum
  • 原文地址:https://www.cnblogs.com/oskyhg/p/7193798.html
Copyright © 2011-2022 走看看