使用DWR实现消息推送

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

你可能感兴趣的:(使用DWR实现消息推送)