----------
我们在前面使用的DWR主要是基于DWR2.X版本的,这里我们针对DWR3进行 介绍,介绍一些提示或技巧。
1. ScriptSession生命周期(创建ScriptSession以及让ScriptSession失效)@H_403_14@
当/dwr/engine.js被包含进页面时ScriptSessions就创建了。默认情况下,ScriptSessions的生命周期由org.directwebremoting.impl.DefaultScriptSessionManager维护。
当 页面被卸载(比如强制刷新页面,卸载再加载)时,将对ScriptSessionManager发出一个远程的DWR调用,通知它让ScriptSession失效。DWR通过这个默认的同步调用,可以很好地让ScriptSession失效。关闭浏览器时,此同步调用可能会导致延迟。如果不喜欢,你可以传递第二个参数给dwr.engine.setNotifyServerOnPageUnload:
第二个可选参数告诉DWR 调用异步卸载器。
注意:在DWR2.X中,页面每刷新一次会多创建一个新的ScriptSession,使用上面的方式可以有效解决这个问题。
由于ScriptSession的创建机制不同于HttpSession,它会在每次页面刷新的时候都会重新创建,而销毁机制却是失去连接或者失效之后一定时间才会自动销毁,这样就可能造成服务端可能就保存了很多的无用的ScriptSession,所以不仅仅会影响性能问题,更重要的是,可能就不能实现你想要的功能。
解决方法是在接收消息的页面,也就是你调用dwr.engine.setActiveReverseAjax(true);的页面调用一个dwr的方法。
dwr.engine.setNotifyServerOnPageUnload(true);
这个方法的功能就是在销毁或刷新页面时销毁当前ScriptSession,这样就保证了服务端获取的ScriptSession集合中没有无效的ScriptSession对象。
2 .非DWR线程(关于请求信息传递到非DWR线程)@H_403_14@
非DWR线程都没有提到DWR线程创建他们。正因为如此:
WebContextFactory().get().getScriptSession()在非DWR线程中将返回null。你需要通过DWR线程向非DWR线程传递数据。
3. ScriptSessionManager(从一个非DWR线程获取ScriptSessionManager)@H_403_14@
可以使用下面的代码:
大多数 反向AJAX实现需要一个单独的线程将数据推给客户端。为每一个DWR请求创建一个线程没有可扩展性。我们建议你使用线程池结合application范围内的DWR创建器。
5 .Browser API(如何针对特定的ScriptSessions)@H_403_14@
DWR的Browser API包含几个比较有用的方法用来更新浏览器。一些Browser方法需要ScriptSessionFilter,并根据ScriptSession的attribute来过滤并针对指定的ScriptSessions。如何使用ScriptSessionFilter与Browser API来区分用户:
5.1 implement ScriptSessionFilter@H_403_14@
- public@H_403_14@@H_403_14@class@H_403_14@TestScriptSessionFilter@H_403_14@implements@H_403_14@ScriptSessionFilter{@H_403_14@@H_403_14@
- @H_403_14@
- private@H_403_14@StringattributeName;@H_403_14@@H_403_14@
- @H_403_14@
- public@H_403_14@TestScriptSessionFilter(StringattributeName){@H_403_14@@H_403_14@
- this@H_403_14@.attributeName=attributeName;@H_403_14@@H_403_14@
- }@H_403_14@
- public@H_403_14@@H_403_14@boolean@H_403_14@match(ScriptSessionsession){@H_403_14@@H_403_14@
- Objectcheck=session.getAttribute(attributeName);@H_403_14@
- return@H_403_14@(check!=@H_403_14@null@H_403_14@&&check.equals(Boolean.TRUE));@H_403_14@@H_403_14@
- }@H_403_14@
- }@H_403_14@
5.3 在你的反向AJAX线程中使用ScriptSessionFilter@H_403_14@
- ScriptSessionFilterfilter=@H_403_14@new@H_403_14@TestScriptSessionFilter(attributeName);@H_403_14@@H_403_14@
- Browser.withPageFiltered(page,filter,new@H_403_14@Runnable(){@H_403_14@@H_403_14@
- public@H_403_14@@H_403_14@void@H_403_14@run(){@H_403_14@@H_403_14@
- //调用DWR的Util类中的setValue方法,用页面上某个元素的ID作为第一个参数的值,第二个参数就是要设置给这个元素的值@H_403_14@@H_403_14@@H_403_14@
- Util.setValue("divID"@H_403_14@,@H_403_14@"valueofdiv"@H_403_14@);@H_403_14@@H_403_14@
- }@H_403_14@
- });@H_403_14@
- ScriptSessionFilterfilter=@H_403_14@new@H_403_14@TestScriptSessionFilter(attributeName);@H_403_14@@H_403_14@
- Browser.withPageFiltered(page,new@H_403_14@Runnable(){@H_403_14@@H_403_14@
- public@H_403_14@@H_403_14@void@H_403_14@run(){@H_403_14@@H_403_14@
- //调用你页面上的一个命名函数(js方法)。注:用ScriptsSessions.addFunctionCall@H_403_14@@H_403_14@@H_403_14@
- //发起这个函数调用的ScriptSessions要匹配TestScriptSessionFilter@H_403_14@@H_403_14@@H_403_14@
- ScriptSessions.addFunctionCall("yourJavaScriptFunctionName"@H_403_14@,arg1,arg2,etc.);@H_403_14@@H_403_14@
- }@H_403_14@
- });@H_403_14@
6. ScriptSession(在ScriptSession中设置区分属性)@H_403_14@
区分用户在同一页上最常见的方式之一,是在ScriptSession上设置属性与在一个反向Ajax线程上获取它们。目前在ScriptSession上有两个最好的设置属性的方法:
6.1 调用一个远程的DWR方法@H_403_14@
- public@H_403_14@@H_403_14@void@H_403_14@remoteMethod(){@H_403_14@@H_403_14@
- Stringvalue="someValue"@H_403_14@;@H_403_14@//thismaycomefromtheHttpSessionforexample@H_403_14@@H_403_14@@H_403_14@
- ScriptSessionscriptSession=WebContextFactory.get().getScriptSession();@H_403_14@
- scriptSession.setAttribute("key"@H_403_14@,value);@H_403_14@@H_403_14@
- }@H_403_14@
- public@H_403_14@@H_403_14@void@H_403_14@sessionCreated(ScriptSessionEventev){@H_403_14@@H_403_14@
- HttpSessionsession=WebContextFactory.get().getSession();@H_403_14@
- StringuserId=(String)session.getAttribute("userId"@H_403_14@);@H_403_14@@H_403_14@
- ev.getSession().setAttribute("userId"@H_403_14@,userId);@H_403_14@@H_403_14@
- }@H_403_14@
7. ScriptSessionListeners(当ScriptSession创建或销毁时,如何使用ScriptSessionListeners做处理)@H_403_14@
你需要如下代码:
- Containercontainer=ServerContextFactory.get().getContainer();@H_403_14@@H_403_14@
- ScriptSessionManagermanager=container.getBean(ScriptSessionManager.class@H_403_14@);@H_403_14@@H_403_14@
- ScriptSessionListenerlistener=new@H_403_14@ScriptSessionListener(){@H_403_14@@H_403_14@
- public@H_403_14@@H_403_14@void@H_403_14@sessionCreated(ScriptSessionEventev){@H_403_14@@H_403_14@
- HttpSessionsession=WebContextFactory.get().getSession();@H_403_14@
- StringuserId=(String)session.getAttribute("userId"@H_403_14@);@H_403_14@@H_403_14@
- ev.getSession().setAttribute("userId"@H_403_14@,userId);@H_403_14@@H_403_14@
- }@H_403_14@
- public@H_403_14@@H_403_14@void@H_403_14@sessionDestroyed(ScriptSessionEventev){}@H_403_14@@H_403_14@
- };@H_403_14@
- manager.addScriptSessionListener(listener);@H_403_14@
7.1 在DWR servlet初始化后,扩展DWR Servlet并执行上述代码@H_403_14@
7.2 在一个Servlet中执行上述代码,并把这个Servlet的@H_403_14@ <load-on-startup/>值设置得要比DWR servlet的<load-on-startup/>值高