最近项目要实现一个消息推送的功能,主要就是发送站内信或者系统主动推送消息给当前在线的用户。每次的消息内容保存数据库,方便用户下次登录后也能看到。如果当前用户在线,收到站内信就主动弹出提示。一开始想到的是前台定时轮询通过ajax查询是否有未读消息。但是这种对系统压力太大。然后网上查询dwr可以主动实时推送消息。现把实现代码贴出来,方便以后使用。
web.xml加入如下配置
<!-- dwr 实时推送 start--> <servlet> <servlet-name>dwr</servlet-name> <servlet-class>org.directwebremoting.spring.DwrSpringServlet </servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/dwr.xml</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>debug</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>logLevel</param-name> <param-value>WARN</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> <!-- dwr 实时推送 end -->
web.xml同级目录下新建dwr.xml
<?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> <!-- dwr 实时推送 end--> <create creator="new" javascript="MessagePush"> <param name="class" value="com.xsw.dwrMsg.service.MessagePush"/> </create> <create creator="new" javascript="TestPush"> <param name="class" value="com.xsw.dwrMsg.service.TestPush"/> </create> <!-- dwr 实时推送 end--> </allow> </dwr>
MessagePush类
/** * 版权所有(C) 2016 xsw * @author xsw * @date 2017-6-23 下午05:38:43 */ package com.xsw.dwrMsg.service; import javax.servlet.ServletException; import org.directwebremoting.ScriptSession; import org.directwebremoting.WebContextFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @ClassName: MessagePush * @Description: TODO() * @author xsw * @date 2017-6-23 下午05:38:43 * */ public class MessagePush { private static Logger logger = LoggerFactory.getLogger(MessagePush.class); public void onPageLoad(String userId) { ScriptSession scriptSession = WebContextFactory.get().getScriptSession(); scriptSession.setAttribute(userId, userId); DwrScriptSessionManagerUtil dwrScriptSessionManagerUtil = new DwrScriptSessionManagerUtil(); try { dwrScriptSessionManagerUtil.init(); logger.info("["+userId+"]初始化,登录到推送的页面,站内信发送页面"); } catch (ServletException e) { e.printStackTrace(); } } }
DwrScriptSessionManagerUtil工具类
/** * 版权所有(C) 2016 xsw * @author xsw * @date 2017-6-26 下午06:31:46 */ package com.xsw.dwrMsg.service; import javax.servlet.ServletException; import javax.servlet.http.HttpSession; import org.directwebremoting.Container; import org.directwebremoting.ServerContextFactory; import org.directwebremoting.WebContextFactory; import org.directwebremoting.event.ScriptSessionEvent; import org.directwebremoting.event.ScriptSessionListener; import org.directwebremoting.extend.ScriptSessionManager; import org.directwebremoting.servlet.DwrServlet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ylink.eu.base.web.EUWebUtil; /** * @ClassName: DwrScriptSessionManagerUtil * @Description: TODO() * @author xsw * @date 2017-6-26 下午06:31:46 * */ public class DwrScriptSessionManagerUtil extends DwrServlet{ private static final long serialVersionUID = -7504612622407420071L; private static Logger logger = LoggerFactory.getLogger(DwrScriptSessionManagerUtil.class); public void init()throws ServletException { Container container = ServerContextFactory.get().getContainer(); ScriptSessionManager manager = container.getBean(ScriptSessionManager.class); ScriptSessionListener listener = new ScriptSessionListener() { public void sessionCreated(ScriptSessionEvent ev) { //HttpSession session = WebContextFactory.get().getSession(); String userId =EUWebUtil.getUserContext().getAccountName(); logger.info("a ScriptSession is created!["+userId+"]"); ev.getSession().setAttribute("userId", userId); } public void sessionDestroyed(ScriptSessionEvent ev) { logger.info("a ScriptSession is distroyed"); } }; manager.addScriptSessionListener(listener); } }
TestPush类
/** * 版权所有(C) 2016 xsw * @author xsw * @date 2017-6-26 下午05:42:51 */ package com.xsw.dwrMsg.service; import java.util.Collection; import org.directwebremoting.Browser; import org.directwebremoting.ScriptBuffer; import org.directwebremoting.ScriptSession; import org.directwebremoting.ScriptSessionFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @ClassName: TestPush * @Description: TODO() * @author xsw * @date 2017-6-26 下午05:42:51 * */ public class TestPush { private static Logger logger = LoggerFactory.getLogger(TestPush.class); public void sendMessageAuto(String userid, String message){ logger.info("发送消息["+message+"]给["+userid+"]"); final String userId = userid; final String autoMessage = message; Browser.withAllSessionsFiltered(new ScriptSessionFilter() { public boolean match(ScriptSession session){ if (session.getAttribute("userId") == null) return false; else return (session.getAttribute("userId")).equals(userId); } }, new Runnable(){ private ScriptBuffer script = new ScriptBuffer(); public void run(){ script.appendCall("showMessage", autoMessage); Collection<ScriptSession> sessions = Browser .getTargetSessions(); for (ScriptSession scriptSession : sessions){ scriptSession.addScript(script); } } }); } }
引入JavaScript文件,具体如下:
<script type="text/javascript" src="<%=basepath%>dwr/engine.js"></script> <script type="text/javascript" src="<%=basepath%>dwr/util.js"></script> <script type="text/javascript" src="<%=basepath%>dwr/interface/MessagePush.js"></script>
接收消息html页面具体内容代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>DWR DEMO</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <script type='text/javascript' src='dwr/engine.js'></script> <script type='text/javascript' src='dwr/util.js'></script> <script type="text/javascript" src="dwr/interface/MessagePush.js"></script> <script type="text/javascript"> //通过该方法与后台交互,确保推送时能找到指定用户 function onPageLoad(){ var userId = '${userinfo.userId}'; MessagePush.onPageLoad(userId); } //推送信息 function showMessage(autoMessage){ alert(autoMessage); } </script> <body onload="onPageLoad();dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);;"> This is my DWR DEOM page. <hr> <br> <div id="DemoDiv">demo</div> </body> </html>
发送消息html页面具体内容代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'MyJsp.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <script type='text/javascript' src='dwr/engine.js'></script> <script type='text/javascript' src='dwr/util.js'></script> <script type='text/javascript' src='dwr/interface/TestPush.js'></script> <script type="text/javascript"> function testPush() { var msg = document.getElementById("msgId").value; TestPush.sendMessageAuto(msg,"www.xiongge.club"); } </script> </head> <body> id值: <input type="text" name="msgId" id="msgId" /> <br /> <input type="button" value="Send" onclick="testPush()" /> </body> </html>
以上基本完成一个实时推送的功能。同时登陆用户A和B到系统,在A页面发送消息给B,B会alert出A发送的消息。以上代码仅供参考,优化扩展的方式有很多,欢迎交流。