最近项目要实现一个消息推送的功能,主要就是发送站内信或者系统主动推送消息给当前在线的用户。每次的消息内容保存数据库,方便用户下次登录后也能看到。如果当前用户在线,收到站内信就主动弹出提示。一开始想到的是前台定时轮询通过ajax查询是否有未读消息。但是这种对系统压力太大。然后网上查询dwr可以主动实时推送消息。现把实现代码贴出来,方便以后使用。
web.xml加入如下配置
dwr
org.directwebremoting.spring.DwrSpringServlet
config
/WEB-INF/dwr.xml
crossDomainSessionSecurity
false
allowScriptTagRemoting
true
classes
java.lang.Object
activeReverseAjaxEnabled
true
initApplicationScopeCreatorsAtStartup
true
maxWaitAfterWrite
3000
debug
true
logLevel
WARN
dwr
/dwr/*
web.xml同级目录下新建dwr.xml
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 sessions = Browser
.getTargetSessions();
for (ScriptSession scriptSession : sessions){
scriptSession.addScript(script);
}
}
});
}
}
引入JavaScript文件,具体如下:
接收消息html页面具体内容代码如下:
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
DWR DEMO//通过该方法与后台交互,确保推送时能找到指定用户
function onPageLoad(){
var userId = '${userinfo.userId}';
MessagePush.onPageLoad(userId);
}
//推送信息
function showMessage(autoMessage){
alert(autoMessage);
}
This is my DWR DEOM page.
发送消息html页面具体内容代码如下:
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
My JSP 'MyJsp.jsp' starting pagefunction testPush() {
var msg = document.getElementById("msgId").value;
TestPush.sendMessageAuto(msg,"www.xiongge.club");
}
id值:
以上基本完成一个实时推送的功能。同时登陆用户A和B到系统,在A页面发送消息给B,B会alert出A发送的消息。以上代码仅供参考,优化扩展的方式有很多,欢迎交流。