dwr消息推送

閒來無事,把本身關於對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

相關文章
相關標籤/搜索