zoukankan      html  css  js  c++  java
  • dwr推送技术深入研究

    DWR 工作原理:

      是通过动态把 Java 类生成为 Javascript。它的代码就像 Ajax 一样,你感觉调用就像发生在浏览器端,但是实际上代码调用发生在服务器端,DWR 负责数据的传递和转换。这种从 Java 到JavaScript的远程调用功能的方式使DWR用起来有种非常像RMI或者SOAP的常规RPC机制,而且DWR的优点在于不需要任何的网页浏览器插件就能运行在网页上。

      Java 从根本上讲是同步机制,然而 AJAX 却是异步的。所以你调用远程方法时,当数据已经从网络上返回的时候,你需要提供有反调 (callback) 功能的 DWR,即你的js代码调用最后一个参数是一个回调函数,由回调函数处理数据返回后想做的操作。

    Comet

    Comet方式通俗的说就是一种长连接机制(long lived http)。同样是由Browser端主动发起请求,但是Server端以一种似乎非常慢的响应方式给出回答。这样在这个期间内,服务器端可以使用同一个connection把要更新的数据主动发送给Browser。因此请求可能等待较长的时间,期间没有任何数据返回,但是一旦有了新的数据,它将立即被发送到客户机。Comet又有很多种实现方式,但是总的来说对Server端的负载都会有增加.虽然对于单位操作来说,每次只需要建议一次connection,但是由于connection是保持较长时间的,对于 server端的资源的占用要有所增加。

    优点: 实时性好(消息延时小);性能好(能支持大量用户)

    缺点: 长期占用连接,丧失了无状态高并发的特点。

    应用: 股票系统、实时通讯。


    1.先配置web.xml

    <!-- dwr start -->
    <servlet>
    <!-- dwr框架的核心控制器 -->
    <servlet-name>dwr-invoker</servlet-name>
    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
    <!-- 在服务器端启用反向ajax -->
    <init-param>
    <param-name>activeReverseAjaxEnabled</param-name>
    <param-value>true</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>org.directwebremoting.extend.ScriptSessionManager </param-name>
    <param-value>com.worklite.core.tools.dwr.DWRScriptSessionManager</param-value>
    </init-param>
    <!-- 在服务器启动阶段,该servlet实例被创建 -->
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>dwr-invoker</servlet-name>
    <!-- 发送如下的请求,都会交给dwr的核心控制器处理 -->
    <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>
    <!-- dwr end -->

    2.新建dwr.xml

    <?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 creator="new" javascript="DwrPush">
    <param name="class" value="com.worklite.core.tools.dwr.DwrPush"/>
    </create>

    <create creator="new" javascript="ClientInitUtil">
    <param name="class" value="com.worklite.core.tools.dwr.ClientInitUtil"/>
    </create>

    <create creator="new" javascript="WebMultiplePushUtil">
    <param name="class" value="com.worklite.core.tools.dwr.WebMultiplePushUtil"/>
    </create>

    <create creator="new" javascript="WebSinglePushUtil">
    <param name="class" value="com.worklite.core.tools.dwr.WebSinglePushUtil"/>
    </create>

    <create creator="new" javascript="WebSingleGamePushUtil">
    <param name="class" value="com.worklite.core.tools.dwr.WebSingleGamePushUtil"/>
    </create>

    </allow>

    </dwr>

    3.编写后台需要的类。

    (1)DWRScriptSessionListener

    public class DWRScriptSessionListener implements ScriptSessionListener {

    //维护一个Map key为session的Id, value为ScriptSession对象
    public static final Map<String, ScriptSession> scriptSessionMap = new MirrorMap<String, ScriptSession>();

    /**
    * ScriptSession创建事件
    */
    @Override
    public void sessionCreated(ScriptSessionEvent event) {
    WebContext webContext = WebContextFactory. get();
    HttpSession session = webContext.getSession();
    ScriptSession scriptSession = event.getSession();
    scriptSessionMap.put(session.getId(), scriptSession); //添加scriptSession
    }

    /**
    * ScriptSession销毁事件
    */
    @Override
    public void sessionDestroyed(ScriptSessionEvent event) {
    //WebContext webContext = WebContextFactory. get();
    //HttpSession session = webContext.getSession();
    //scriptSessionMap.remove(session.getId()); //移除scriptSession
    }

    /**
    * 获取所有ScriptSession
    */
    public static Collection<ScriptSession> getScriptSessions(){
    return scriptSessionMap.values();
    }


    public static ScriptSession getScriptSession(String str){
    Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
    //遍历每一个ScriptSession
    for (ScriptSession scriptSession : sessions){
    String tag = (String)scriptSession.getAttribute(str);
    if ( tag!=null&&str.equals(tag)) {
    return scriptSession;
    }

    }
    return null;

    }

    public static int Count(String wId){

    Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
    //遍历每一个ScriptSession
    int i=0;
    for (ScriptSession scriptSession : sessions){
    String tag = (String)scriptSession.getAttribute(wId);
    if ( tag!=null&&wId.equals(tag)) {
    i++;
    }

    }
    return i;

    }

    public static boolean getCustomList(String wId,int customId){

    Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
    //遍历每一个ScriptSession
    for (ScriptSession scriptSession : sessions){
    String tagId=customId+wId;
    String tag = (String)scriptSession.getAttribute(tagId);

    if(tag!=null&&tagId.equals(tag)){
    return true;
    }

    }
    return false;

    }


    public static List<String> getCustomList(String wId){
    List<String> customList=new ArrayList<String>();
    Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
    //遍历每一个ScriptSession
    for (ScriptSession scriptSession : sessions){
    Iterator<String> iter = scriptSession.getAttributeNames();
    while(iter.hasNext()){
    String str=iter.next();
    if(str!=null&&str.contains(String.valueOf(","+wId))){
    String customId = str.split(",")[0];
    if (!customList.contains(customId))
    customList.add(customId);
    }
    }
    }


    return customList;

    }

    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) {

    WebContext webContext = WebContextFactory. get();
    HttpSession session = webContext.getSession();
    ScriptSession scriptSession = ev.getSession();
    scriptSessionMap.put(session.getId(), scriptSession); //添加scriptSession
    }

    public void sessionDestroyed(ScriptSessionEvent ev) {

    WebContext webContext = WebContextFactory. get();
    HttpSession session = webContext.getSession();
    ScriptSession scriptSession = scriptSessionMap.remove(session.getId()); //移除scriptSession
    }

    };

    manager.addScriptSessionListener(listener);

    }

    }

    (2)DWRScriptSessionManager

    public class DWRScriptSessionManager extends DefaultScriptSessionManager {

    public DWRScriptSessionManager(){
    //绑定一个ScriptSession增加销毁事件的监听器
    this.addScriptSessionListener( new DWRScriptSessionListener());
    Log.debug( "bind DWRScriptSessionListener");
    }
    }

    (3)DwrPush注册scriptSession 

    public class DwrPush {

    public void onPageLoad(final String tag){
    //获取当前的ScriptSession
    ScriptSession scriptSession = WebContextFactory.get().getScriptSession();
    scriptSession.setAttribute( tag, tag);
    }
    }

    (4)WebMultiplePushUtil 用于群发

    public class WebMultiplePushUtil {

    public void push(final String wId,final String content,final String command){

    //过滤器
    ScriptSessionFilter filter = new ScriptSessionFilter() {

    public boolean match(ScriptSession scriptSession) {

    String tag = (String)scriptSession.getAttribute(wId);
    if ( tag== null) {
    return false;
    } else {
    return wId.equals(tag);
    }
    }
    };

    Runnable run = new Runnable(){
    private ScriptBuffer script = new ScriptBuffer();

    public void run() {
    //设置要调用的 js及参数
    script.appendCall( "showMessage","{"wId":""+wId+"","content":""+content+"","command":""+command+""}");
    //得到所有ScriptSession
    Collection<ScriptSession> sessions = Browser.getTargetSessions();
    //遍历每一个ScriptSession
    for (ScriptSession scriptSession : sessions){
    scriptSession.addScript( script);
    }
    }
    };
    //执行推送
    Browser. withAllSessionsFiltered(filter, run); //注意这里调用了有filter功能的方法
    }
    }

    (5)WebSingleGamePushUtil 用于单发游戏

    public class WebSingleGamePushUtil {

    public void push(final String customId,final String wId,final Webcast_game_push push){

    Runnable run = new Runnable(){
    private ScriptBuffer script = new ScriptBuffer();
    public void run() {
    //设置要调用的 js及参数
    script.appendCall( "show",JSONObject.fromObject(push).toString());
    ScriptSession scriptSession =DWRScriptSessionListener.getScriptSession(customId+","+wId);
    if(null!=scriptSession){
    scriptSession.addScript( script);
    }

    }
    };

    //执行推送
    Browser.withAllSessions(run);
    }
    }

    (6)WebSinglePushUtil 用于单发通知

    public class WebSinglePushUtil {

    public void push(final String customId,final String wId,final String content,final String command){
    //过滤器
    ScriptSessionFilter filter = new ScriptSessionFilter() {

    public boolean match(ScriptSession scriptSession) {
    String tagId=customId+","+wId;
    String tag = (String)scriptSession.getAttribute(tagId);
    if ( tag== null) {
    return false;
    } else {
    return tagId.equals(tag);
    }
    }
    };

    Runnable run = new Runnable(){
    private ScriptBuffer script = new ScriptBuffer();
    public void run() {
    //设置要调用的 js及参数
    script.appendCall( "show","{"customId":""+customId+"","wId":""+wId+"","content":""+content+"","command":""+command+""}");
    //得到所有ScriptSession
    Collection<ScriptSession> sessions = Browser.getTargetSessions();
    //遍历每一个ScriptSession
    for (ScriptSession scriptSession : sessions){
    scriptSession.addScript( script);
    }
    }
    };

    //执行推送
    Browser. withAllSessionsFiltered(filter, run); //注意这里调用了有filter功能的方法
    }
    }

    4.在jsp页面引入相应的js

    <script type="text/javascript" src="/worklite/dwr/engine.js"></script>
    <script type="text/javascript" src="/worklite/dwr/util.js"></script>
    <script type="text/javascript" src="/worklite/dwr/interface/DwrPush.js"></script>

    dwr.engine.setActiveReverseAjax(true);
    dwr.engine.setAsync(true);

    dwr.engine._errorHandler = function(message, ex) {dwr.engine._debug("Error: " + ex.name + ", " + ex.message, true);};

    <body onload="dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);onPageLoad();">

    在页面上要先掉用下DwrPush.onPageLoad(),加入scriptSession

    function onPageLoad(){
    DwrPush.onPageLoad(wId);
    DwrPush.onPageLoad(""+customId+","+wId);
    }

    然后在代码中调用相应的push方法即可完成推送。

  • 相关阅读:
    Docker _简单使用
    IDEA常见问题
    Linux安装JDK
    vitualbox网络设置链接
    MQ对比
    乐观锁和悲观所在数据库中的实现
    11.08 JS知识
    11.07知识整理
    11.06 知识整理
    本周知识整理
  • 原文地址:https://www.cnblogs.com/momo1210/p/6283578.html
Copyright © 2011-2022 走看看