dwr支持如下3种模式的消息推送:
- Polling,浏览器每隔一段时间向服务器发出请求,查看是否有更新的内容;
- Comet,
- Piggyback,服务器等待浏览器下一次发出请求时,将更新的内容合并到响应一起返回。
默认使用Piggyback模式,使用Polling/Comet模式需要额外的配置。
DWR简单入门介绍了基于DWR构建项目。
使用Maven构建项目,在pom.xml中添加如下配置
oss-sonatype-snapshots
OSS Sonatype Snapshots Repository
http://oss.sonatype.org/content/repositories/snapshots
false
true
...
org.directwebremoting
dwr
3.0.0-SNAPSHOT
commons-logging
commons-logging
1.2
org.apache.tomcat
catalina
6.0.44
使用的容器是Tomcat(与使用Jetty的配置不同),在web.xml中添加如下配置
dwr-invoker
org.directwebremoting.server.tomcat.DwrCometProcessor
debug
true
activeReverseAjaxEnabled
true
maxWaitAfterWrite
1000
dwr-invoker
/dwr/*
dwr.xml中的配置
采用的调试方式是,打开接收页面(receiver.jsp)和发送页面(sender.jsp),在发送页面将消息发送至服务端,由服务端将消息推送至接受页面。JSP文件中使用JQuery
替代了dwr提供的。
接收页面(receiver.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
消息推送
接受消息推送
发送页面(sender.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
消息推送
发送消息推送
ID:消息: 发送
me/util/MessagePushUtil.java中的内容
package me.util;
import java.util.Collection;
import javax.servlet.ServletException;
import org.apache.log4j.Logger;
import org.directwebremoting.Browser;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ScriptSessionFilter;
import org.directwebremoting.WebContextFactory;
import me.message.MessagePushServlet;
public class MessagePushUtil {
private static final Logger LOGGER = Logger.getLogger(MessagePushUtil.class);
public void onPageLoad(String userID) {
ScriptSession scriptSession = WebContextFactory.get().getScriptSession();
// 工厂方法get()返回WebContext实例,通过WebContext获取servlet参数
// ScriptSession与HttpSession类似
scriptSession.setAttribute("uid", userID);
MessagePushServlet mpServlet = new MessagePushServlet();
try {
mpServlet.init();
LOGGER.info(String.format("消息推送初始化成功,uid:%s", userID));
} catch (ServletException e) {
LOGGER.error(String.format("消息推送初始化错误,uid:%s", userID));
}
}
/**
* 根据userID向指定用户推送消息
*
* @param userID
* @param autoMessage
*/
public void sendMessageAuto(String userID, String autoMessage) {
final String uid = userID;
final String message = autoMessage;
Browser.withAllSessionsFiltered(new ScriptSessionFilter() {
// 实现过滤器中的match()方法
public boolean match(ScriptSession session) {
if (session.getAttribute("uid") == null)
return false;
else
return (session.getAttribute("uid")).equals(uid);
}
}, new Runnable() {
private ScriptBuffer script = new ScriptBuffer();
public void run() {
// 调用JSP中定义的showMessage()方法,实现消息的前端显示
script.appendCall("showMessage", message);
Collection sessions = Browser.getTargetSessions();
for (ScriptSession scriptSession : sessions) {
scriptSession.addScript(script);
}
LOGGER.info(String.format("向用户推送消息,uid:%s,message:%s", uid, message));
}
});
}
}
me/message/MessagePushServlet.java中的内容,覆盖DwrServlet中的init()方法实现ScriptSession监听器,在页面中加入engine.js时,ScriptSession创建,默认由org.directwebremoting.impl.DefaultScriptSessionManager管理,当发生unload事件时,DefaultScriptSessionManager会被通知销毁ScriptSession。
package me.message;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
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;
public class MessagePushServlet extends DwrServlet {
private static final long serialVersionUID = 4298890285665323894L;
private static final Logger LOGGER = Logger.getLogger(MessagePushServlet.class);
@Override
public void init() throws ServletException {
Container container = ServerContextFactory.get().getContainer();
// 工厂方法get()返回ServerContext实例
ScriptSessionManager manager = container.getBean(ScriptSessionManager.class);
ScriptSessionListener listener = new ScriptSessionListener() {
public void sessionCreated(ScriptSessionEvent ev) {
HttpSession session = WebContextFactory.get().getSession();
String userID = (String) session.getAttribute("uid");
LOGGER.info("a ScriptSession is created");
ev.getSession().setAttribute("uid", userID);
}
public void sessionDestroyed(ScriptSessionEvent ev) {
LOGGER.info("a ScriptSession is distroyed");
}
};
manager.addScriptSessionListener(listener);
}
}
运行前还要修改Tomcat下的server.xml中的配置
运行项目,打开http://localhost:8080/receiver.jsp,页面加载时,调用
messagePush.onPageLoad('<%=session.getAttribute("uid")%>');
调用服务端的me.util.MessagePushUtil.onPageLoad(String userID)方法,初始化成功(可以使用字符串,如"123456789",替换'<%=session.getAttribute("uid")%>')。打开http://localhost:8080/sender.jsp,填写刚才的uid(123456789)和消息内容,点击发送,调用
messagePush.sendMessageAuto($('#uid').val(), $('#msg').val());
调用服务端的me.util.MessagePushUtil.sendMessageAuto(String userID, String autoMessage)方法,调用receiver.jsp的showMessage(autoMessage)方法,可以在接收页面看到来自服务端推送的消息。
页面预览如下,
除此之外,在log4j.properties中添加类似的配置
log4j.rootCategory=INFO, console
log4j.category.org.directwebremoting.log=INFO, dwr, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%5p] %d{yyyy-MM-dd HH:mm:ss} %l - %m%n
log4j.appender.dwr=org.apache.log4j.RollingFileAppender
log4j.appender.dwr.File=../logs/dwr.log
log4j.appender.dwr.MaxFileSize=100KB
log4j.appender.dwr.MaxBackupIndex=1
log4j.appender.dwr.layout=org.apache.log4j.PatternLayout
log4j.appender.dwr.layout.ConversionPattern=[%5p] %d{yyyy-MM-dd HH:mm:ss} %l - %m%n
参考资料
DWR3实现服务器端向客户端精确推送消息
DWR简单入门
Reverse Ajax
Logging