zoukankan      html  css  js  c++  java
  • jsp实时显示后台批处理进度

    这两天在实现一个批处理操作,但是想让前台实时显示后台批处理进度,本想着用复杂一些的框架可以实现异步信息调用

    但是鉴于是内部管理系统,且只有一两个人用到这个功能,所以做了一个简单的长连接方式的实时响应

    有些人说使用ajax请求,定时刷新,个人觉得很耗服务器资源,而且准确的说也不是实时的

    【原文摘自 BearRui(AK-47) 的Bloghttp://www.blogjava.net/BearRui/archive/2010/06/01/ajax_better_experience.html

     

    使用技术:AJAX - onreadystatechange 事件

      详细解释:http://www.runoob.com/ajax/ajax-xmlhttprequest-onreadystatechange.html

      MSDN:https://msdn.microsoft.com/en-us/library/ms535874(VS.85).aspx

    要解决实现上面的功能,需要解决下面几个问题:

       1. 服务器如何在处理一部分数据后传递部分response到浏览器。

       2、浏览器如何能处理服务器传递过来部分数据,并保持http连接直到处理完全完毕。

    解决

      第1个问题,使用flush让response分块进行呈现就可以了,具体请参考我另一遍随笔"flush让页面分块,逐步呈现 http://www.blogjava.net/BearRui/archive/2010/05/19/flush_chunk_encoding.html";

      第2个问题,则需要用到XMLHttpRequest的readyState状态,w3c对 readyState 定义如下几个值:

      UNSENT = 0; // 没有发送请求

      OPENED = 1;    // 已经打开http连接

      HEADERS_RECEIVED = 2; // 接收到response header

      LOADING = 3;          // 真正接收response body   

      DONE = 4;             // 请求接收完毕

    另外的问题: readyState每次返回0-4的状态时,state的值是多少呢?200吗?还是其他?

      首先,status是XMLHttpRequest对象的一个属性,表示响应的HTTP状态码。

      在HTTP1.1协议下,HTTP状态码总共可分为5大类,如下表所示:

      1XX    服务器收到请求,需要继续处理。例如101状态码,表示服务器将通知客户端使用更高版本的HTTP协议。 

      2XX    请求成功。例如200状态码,表示请求所希望的响应头或数据体将随此响应返回。 

      3XX    重定向。例如302状态码,表示临时重定向,请求将包含一个新的URL地址,客户端将对新的地址进行GET请求。 

      4XX    客户端错误。例如404状态码,表示客户端请求的资源不存在。 

      5XX    服务器错误。例如500状态码,表示服务器遇到了一个未曾预料的情况,导致了它无法完成响应,一般来说,这个问题会在程序代码出错时出现。

      其次,经过测试,每次readyState有状态变化,如果后台不异常,那么返回都是200,所以当readyState返回4时候,需要对state=200做判断,否则提示批处理异常

    下面来看代码

        ===================前端代码====================
    
        //打开框
        $('#settle-batch').dialog("center");
        settleBatch.html("");
        $('#settle-batch').dialog('open').dialog('setTitle', "批量处理进度显示");
    
        //发送批处理请求
        var xhr = new window.XMLHttpRequest();
        if(!window.XMLHttpRequest){
            try {
                xhr = new window.ActiveXObject("Microsoft.XMLHTTP");
            } catch(e) {
                alertMsg("失败", "创建请求失败,请重试");
            }
        }
        xhr.open("post","http://localhost:8081/WMS/agentsettle/batch");
        settleBatch.append("<p>正在发送批处理请求 ...</p>");
    
        //处理实时回调信息
        var oldSize=0;
        xhr.onreadystatechange = function(){
            var readyState = xhr.readyState;
            //成功发送请求
            if(readyState == 2){
                settleBatch.append("<p>启动上月代理分成批处理</p>");
                settleBatch.append("<p style='margin: 10px;'></p>");
            }
            //接收事实数据
            if(readyState > 2){
                var tmpText = xhr.responseText.substring(oldSize);
                oldSize = xhr.responseText.length;
                if(tmpText.length > 0 ){
                    // 设置文本
                    var str = tmpText.replace(/"/g, "");
                    settleBatch.append("<p>" + str + "</p>");
                }
            }
            //处理成功
            if(readyState == 4){
                settleBatch.append("<p style='margin: 10px;'></p>");
                if (xhr.status === 200) {
                    settleBatch.append("<p>批处理完成 !!!</p>");
                } else {
                    settleBatch.append("<p>批处理异常结束 !!!???</p>");
                }
            }
        }
        xhr.send(null);
               =============后台代码==================
        
                response.setHeader("Content-Type","application/x-javascript");
                //设置out的字符编码,否则到前台可能中文乱码
                response.setCharacterEncoding("UTF-8");
                PrintWriter out = getResponse().getWriter();
    
                Thread.sleep(1000);
                out.println("正在处理第1个 ...");
                out.flush();
    
                Thread.sleep(1000);
                out.println("正在处理第2个 ...");
                out.flush();
    
                Thread.sleep(1000);
                out.println("正在处理第3个 ...");
                out.flush();
    
                Thread.sleep(1000);
                out.println("正在处理第4个 ...");


    经测试,现在chrome、firefox、360浏览器都支持readyState=3的处理

      基于Webkit的浏览器支持的不是很好,需要设置Content-Type:application/x-javascript才行(经测试发现Content-Type:text/html在有些情况下正常,有些情况下又不正常,而用application/x-javascript都正常)。

    另外方法

    1、jquery 1.5已经支持onreadysatechange,可以使用

    2、有些 消息异步通讯 的框架也可以实现这样的功能,不过要看实现实时显示的功能复杂度

  • 相关阅读:
    linux三剑客之sed
    线程与循环的区别?
    Notify和NotifyAll的区别?
    no system images installed for this target这个问题如何解决?
    Intent里ACTION的CALL和DIAL的区别?
    onConfigurationChanged方法的使用
    String和StringBuffer的区别?
    Activity的状态保存
    C#将datatable数据转换成JSON数据的方法
    SQL语句:关于复制表结构和内容到另一张表中的SQL语句
  • 原文地址:https://www.cnblogs.com/yingsong/p/5976375.html
Copyright © 2011-2022 走看看