閒來無事,把本身關於對dwr消息推送的實現過程描述一番。javascript
首先第一步,固然在工程中是加入dwr.jar了,接着在web.xml中配置如下代碼java
<servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/config/dwr.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>crossDomainSessionSecurity</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>allowScriptTagRemoting</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>classes</param-name> <param-value>java.lang.Object</param-value> </init-param> <init-param> <param-name>activeReverseAjaxEnabled</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>initApplicationScopeCreatorsAtStartup</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>maxWaitAfterWrite</param-name> <param-value>3000</param-value> </init-param> <init-param> <param-name>logLevel</param-name> <param-value>WARN</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping>
從配置中能夠看出須要新建一個dwr配置文件,以下web
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr//dwr30.dtd"> <dwr> <allow> <!-- <create javascript="udao" creator="spring"> <param name="beanName" value="udao" /> <include method="getUserPage"/> </create> <convert converter="bean" match="com.cpsoft.app.web.domain.PageModel" /> --> <create javascript="MessagePush" creator="spring"> <param name="beanName" value="messagePush" /> </create> <convert converter="bean" match="java.lang.StackTraceElement" /> <convert converter="exception" match="java.lang.Exception" /> </allow> </dwr>
那麼你們能夠看到,我配置了一個messagePush這個對象,那麼我就來講說這個對象吧spring
@Component public class MessagePush { final public static String SCRIPT_SESSION_USERID = "SCRIPT_SESSION_USERID"; final public static String SCRIPT_SESSION_MSG = "showMessage"; //這是頁面上當後臺消息推送時,自動觸發的js方法名稱 private Logger log = Logger.getLogger(this.getClass()); private ScriptSessionListener listener; private boolean isInit = false; public boolean isInit(){ return isInit; } /** * 獲取scriptSession的監聽對象,只須要實例化一次 * @return */ public ScriptSessionListener getListener() { if(listener == null){ listener = new ScriptSessionListener() { public void sessionCreated(ScriptSessionEvent ev) { HttpSession session = WebContextFactory.get().getSession(); Staff staff = SessionUtil.getStaff(session); if(staff!=null){ ev.getSession().setAttribute(SCRIPT_SESSION_USERID, staff.getId()); //與當前登陸用戶相關聯 log.info("a ScriptSession["+staff.getId()+"] is created!"); Map<String, Staff> onlineStaffMap = CacheUtil.getOnlineStaffMap(); //獲取當前的在線用戶 if(!onlineStaffMap.containsKey(staff.getId())) onlineStaffMap.put(staff.getId(), staff); //若是不存在,則將當前用戶加入到緩存中 } if(!isInit) isInit = true; } public void sessionDestroyed(ScriptSessionEvent ev) { String userId = (String) ev.getSession().getAttribute(SCRIPT_SESSION_USERID); log.info("a ScriptSession["+userId+"] is distroyed!"); } }; } return listener; } /** * 初始化dwr監聽,只在程序中調用一次便可 */ public void init(){ if(listener == null){ Container container = ServerContextFactory.get().getContainer(); ScriptSessionManager manager = container .getBean(ScriptSessionManager.class); manager.addScriptSessionListener(getListener()); log.info("the dwr client is inited!"); } } }
這個類的主要做用是初始化監聽,接着若是有了監聽,那如今就能夠推送消息了,請看代碼chrome
/** * 採用dwr的方式向前臺推送消息 * @param userId 用戶Id * @param autoMessage 消息內容 */ private static void sendMessageAuto(final String userId, final String autoMessage) { Browser.withAllSessionsFiltered(new ScriptSessionFilter() { public boolean match(ScriptSession session) { String id = (String) session.getAttribute(MessagePush.SCRIPT_SESSION_USERID); if (id == null || !userId.equals(id)) { //匹配接收人的Id return false; } return true; } }, new Runnable() { private ScriptBuffer script = new ScriptBuffer(); public void run() { script.appendCall(MessagePush.SCRIPT_SESSION_MSG, autoMessage); //推送消息(我在這裏用的是json字符串) Collection<ScriptSession> sessions = Browser.getTargetSessions(); //獲取當前的目標客戶端對象 for (ScriptSession scriptSession : sessions) { scriptSession.addScript(script); } } }); }
說到這裏,後臺工做就告一段落了,接着來講說前臺,首先引入js吧json
<!-- 消息推送 --> <script type='text/javascript' src='${ctx}/dwr/engine.js'></script> <script type='text/javascript' src='${ctx}/dwr/util.js'></script> <script type="text/javascript" src="${ctx}/dwr/interface/MessagePush.js"></script>
在onload 加入緩存
<body onload="dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);">
那麼如今大工告成了,只要後臺調用上面的推送方法,前臺就好自動觸發session
function showMessage(autoMessage){ //alert(autoMessage); if(!callCometShowMsg){ eval("var json="+ autoMessage); g_showTip("消息類型:"+json.MESSAGE_TYPE+"<br />消息內容:"+json.MESSAGE_DATA); }else{ callCometShowMsg(autoMessage); } }
最後說說總結一下把,實測了一下,發現Ie8下反應慢一點,對於chrome,我用的這個版本會有問題, 火狐表現良好app
有什麼問題能夠留言,看到第一時間回覆dom