DWR3实现服务器端向客户端精确推送消息



     研究了一天半,终于模拟出了这个功能,网上DWR的资料不少,但是真正实现客户端向服务器端精确推送消息的只有两篇文章。但是代码都只有一部分,向我这种刚开始学习DWR的人来说要看懂真的蛮难。不过即便如此,http://www.blogjava.net/stevenjohn/archive/2012/07/07/382447.html这片文章还是给了我很大帮助,再次表示感谢,下面我将这两天的研究详细记录下来备忘,也希望能帮助到像我一样的人。只写过程,不写原理(不是不写,而是有些地方我也不太懂),下面开始:

         第一、在项目中引入dwr.jar,然后在web.xml中进行配置,配置如下:

<servlet>  
  
        <servlet-name>dwr-invoker</servlet-name>  
  
        <servlet-class>  
  
            org.directwebremoting.servlet.DwrServlet  
  
        </servlet-class>  
  
        <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>

   第二:在web.xml的同级目录下新建dwr.xml文件,内容如下

  

<!DOCTYPE dwr PUBLIC  
     "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"  
     "http://getahead.org/dwr/dwr30.dtd">  
  
<dwr>  
     <alow>  
          <create creator="new" javascript="MessagePush">  
            <param name="class" value="com.huatech.messageremind.service.MessagePush"/>  
         </create>  
          <create creator="new" javascript="TestPush">  
            <param name="class" value="com.huatech.messageremind.service.Test"/>  
         </create>  
     </alow>  
</dwr>  

   这个是dwr的基本配置,MessagePush在页面的JavaScript中使用,这个是对被推送页面开放的Java类,Test是对推送页面开放的java类。场景:管理员后台登陆,发布一条消息,通过Test推送到后台,后台通过MessagePush推送给指定的用户,当然,至于怎么找到指定的用户,下面会说。

     第三,被推送的页面代码

    

<%@ 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.humanid}';  
            MessagePush.onPageLoad(userId);  
  
          }  
         //推送信息  
         function showMessage(autoMessage){  
                alert(autoMessage);  
                  
        }  
  </script>  
  <body οnlοad="onPageLoad();dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);;">   
    This is my DWR DEOM page. <hr>  
    <br>  
    <div id="DemoDiv">demo</div>  
  </body>  
</html>

    以上代码的简单解释:

     页面页面onload的3个函数都是必须的,后两个是dwr的,第一个是将登录用户的userid与对应   的scriptSession进行处理,以便精确推送的时候能找到推送对象

第四 MessagePush类中实现的方法如下:

  

public void onPageLoad(String userId) {  
  
       ScriptSession scriptSession = WebContextFactory.get().getScriptSession();  
  
       scriptSession.setAttribute(userId, userId);  
  
       DwrScriptSessionManagerUtil dwrScriptSessionManagerUtil = new DwrScriptSessionManagerUtil();  
  
       try {  
  
              dwrScriptSessionManagerUtil.init();  
              System.out.println("cacaca");  
  
       } catch (ServletException e) {  
  
              e.printStackTrace();  
  
       }  
  
}  

里面对应的DwrScriptSessionManagerUtil 对应如下:

 

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;  
  
public class DwrScriptSessionManagerUtil extends DwrServlet{  
  
    private static final long serialVersionUID = -7504612622407420071L;  
  
    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 =((User) session.getAttribute("userinfo")).getHumanid()+"";  
                         System.out.println("a ScriptSession is created!");  
                         ev.getSession().setAttribute("userId", userId);  
                  }  
                  public void sessionDestroyed(ScriptSessionEvent ev) {  
                         System.out.println("a ScriptSession is distroyed");  
                  }  
           };  
           manager.addScriptSessionListener(listener);  
    }  
}  

 第五 推送页面代码:

    

<%@ 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="<%=request.getContextPath() %>/js/jquery-1.5.1.js"></script>  
    <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 test() {  
        var msg = document.getElementById("msgId").value;  
        //msg = {msgId: '1', context: $("#msgContext").val()};  
        TestPush.sendMessageAuto(msg,"哈哈哈");  
          
    }  
    </script>  
  </head>  
    
  <body>  
    id    : <input type="text" name="msgId" id="msgId" /> <br />  
     
    <input type="button" value="Send" οnclick="test()"  />  
      
  </body>  
</html>  

 第六:精确推送要实现的代码:

 
public class Test{  
    public void sendMessageAuto(String userid, String message){  
          
        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);  
                }  
            }  
        });  
    }  
}  

 至此   这个例子的代码都已经贴出来了,应该是可以跑通的,有问题的话可以给我留言。当然,要自己写个登录,然后把userId放到session里面,这个比较简单,就不贴代码了,有问题可以在http://download.csdn.net/detail/luojia_wang/5275588上下载原项目。我只是简单的做了一个能实现功能的例子,还有很多地方要研究,比如跟spring整合,还可能有很多优化,等我继续学习一下再说.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值