首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

5.6  实时动态决策分析方案

所谓实时动态决策分析,是指由软件自动刷新统计结果,从而展示给用户的始终是最新的统计数据,所以用户每次在查看统计数据之前,并不需要手动刷新统计数据。

1.方案分析

随着网络技术和实时监控技术的不断发展,实时动态决策分析在网络监控领域的使用范围也越来越广,例如江河汛情的监控、大气质量的监控、股票行情的监控和机械生产领域的监控等,通过对实时监测软件系统的使用,可以及时的掌握相关信息,并且可以针对各种变化,及时的做出决策和处理办法。

由于通过Ajax技术可以实现JSP页面的无闪烁刷新,所以在实施实时动态决策分析方案时,将采用Ajax技术,引入Ajax技术的页面刷新流程如图5.51所示。

图5.51  引入Ajax技术的页面刷新流程

从图5.51中可以看出,通过Ajax技术每次刷新JSP页面时,都要发出一个异步请求,这个异步请求的作用是负责处理实时统计信息,并返回统计结果。在实施实时动态决策分析方案时,需要完成的主要工作如下:

l          开发实时刷新统计页面;

l          开发负责发出和响应异步请求的Javascript方法;

l          开发负责处理异步请求的Servlet。

2.实施过程

*  实例位置光盘\mr\5\5.5\01

在开发软件监测系统时,都要求软件具有实时刷新的能力,能够自动刷新最新的统计数据,从而保证展示给用户的永远是最新的数据信息,例如股票监测系统、水文监测系统、火车票预售情况监测系统等,本案例实现的是水文监测系统,如图5.52所示,断面流量走势图会随着时间的变化而自动刷新。

图5.52  实时动态决策分析方案效果图

在方案分析中,已经给出了在实施实时动态决策分析方案时,需要完成的主要工作,下面将逐步介绍每项工作的具体实施办法,以及在实施过程中需要注意的一些事项。

首先编写负责显示实时刷新统计结果的JSP页,在编写该页时,有两项主要工作需要完成,一是立即初始化页面信息,另一是加入触发请求刷新的事件,其中负责初始化页面信息的代码如下:

例程5-86  代码位置:光盘\mr\5\5.6\01\index.jsp

System.out.print("------ 手动刷新,"); // 向控制台输出手动刷新标记

JDBC jdbc = new JDBC();

MakeSimulationData msd = new MakeSimulationData();

msd.setJdbc(jdbc);

msd.refresh(); // 刷新模拟数据信息

TimeSeriesChart tsc = new TimeSeriesChart();

tsc.setJdbc(jdbc);

String graphURL=tsc.drawTimeSeries(); // 依据数据生成统计图片,并返回图片的浏览路径

下面通过<img>元素显示图片,代码如下:

<img id="StatChart" src="<%=graphURL %>" usemap="" alt="">

在添加触发请求刷新的事件时,有多种类型,例如鼠标事件onmouseover、键盘事件onkeyup和加载事件onload,由于是实时刷新统计,所以这里采用的是onload事件,具体代码如下:

<body onload="refreshChartRequest()">

然后编写负责发出和响应异步请求的Javascript方法。Javascript代码可以存放在JSP文件中,也可以存放在专门用来存放Javascript代码的JS文件中。

下面的方法createXMLHttpRequest()负责创建XMLHttpRequest对象。在创建XMLHttpRequest对象时,需要考虑到多种情况,当为IE浏览器时,则需要通过ActiveXObject()方法创建,如果IE浏览器的版本较新,创建方式为“new ActiveXObject("Msxml2.XMLHTTP")”,如果较旧则创建方式为“Microsoft.XMLHTTP”;当为其他浏览器时,例如Mozilla﹑Netscape﹑Safari等,创建方式为“new XMLHttpRequest()”,在这种情况下,如果服务器的响应没有XML mime-type header,某些Mozilla浏览器可能无法正常工作,为了解决这个问题,如果服务器响应的header不是text/xml,可以调用xmlHttpRequest对象的overrideMimeType()方法修改该header。创建xmlHttpRequest对象的具体代码如下:

例程5-87  代码位置:光盘\mr\5\5.6\01\JS\ajax.js

function createXMLHttpRequest() {

   if (window.ActiveXObject) {

       try { // 为较新版本的IE浏览器创建xmlHttpRequest对象

              xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");

       }

       catch (e) {

              try { // 为较旧版本的IE浏览器创建xmlHttpRequest对象

                 xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");

              }

              catch (e) {

                 window.alert("创建XMLHttpRequest对象失败,原因如下:" + e);

                 return false;

              }

       }

   } else {

       if (window.XMLHttpRequest) {

              try { // 为其他浏览器创建xmlHttpRequest对象

                 xmlHttpRequest = new XMLHttpRequest();

                 xmlHttpRequest.overrideMimeType("text/xml");

              }

              catch (e) {

                 window.alert("创建XMLHttpRequest对象失败,原因如下:" + e);

                 return false;

              }

       }

   }

}

下面编写负责处理onload事件的refreshChartRequest()方法,该方法先是调用createXMLHttpRequest()方法创建xmlHttpRequest对象,然后调用refreshChartSend()方法发出异步请求,具体代码如下:

例程5-88  代码位置:光盘\mr\5\5.6\01\JS\ajax.js

function refreshChartRequest() {

   createXMLHttpRequest();

   refreshChartSend();

}

下面编写refreshChartSend()方法。在refreshChartSend()方法中先是调用xmlHttpRequest对象的open()方法,该方法有三个入口参数,各自的作用依次为:

l          第1个参数用来设置发出HTTP请求的方式,可选值为GET和POST,要求必须大写,否则某些浏览器(例如Firefox)可能无法处理请求;

l          第2个参数用来设置请求的路径,可以是绝对路径,也可以是相对路径,同时可以加入请求参数;

l          第3个参数用来设置发出HTTP请求的模式,当设为true时表示采用异步模式发送。

然后调用setRequestHeader()方法设置请求的头文件;紧接着通过onreadystatechange属性设置回调方法,所谓回调方法,是指在请求处理结束后Ajax控制器自动调用的用来处理响应结果的方法;最后调用send()方法,发出本次请求。具体代码如下:

例程5-89  代码位置:光盘\mr\5\5.6\01\JS\ajax.js

function refreshChartSend() {

   var url = "servlet/RefreshChart";

   xmlHttpRequest.open("GET", url, true);

   xmlHttpRequest.setRequestHeader("Content-type",

       "application/x-www-form-urlencoded");

   xmlHttpRequest.onreadystatechange = refreshChartResponse;

   xmlHttpRequest.send();

}

*  注意:在设置回调方法时,在回调方法的名称后不能有括号,例如不可以设置为:xmlHttpRequest.onreadystatechange = refreshChartResponse()!

下面编写回调方法refreshChartResponse()。只有在已经收到服务器的完整响应时,才可以处理响应结果,可以通过xmlHttpRequest对象的readyState属性判断服务器的响应状态,当为4时代表已经收到服务器的完整响应。确定已经收到服务器的完整响应后,还要通过xmlHttpRequest对象的status属性判断服务器的响应状态,当为200时代表服务器的响应状态正常,否则表示并未返回预期的结果,status属性其他值的含义请参见W3C文档。在已经收到服务器的完整响应、并且服务器的响应状态正常的情况下,就可以读取服务器返回的响应结果了,服务器返回的响应结果有两种方式,分别是:

l          字符串形式:适合于返回结果较简单的情况,例如本案例只返回一个图片的浏览路径,或者true或false等;

l          XML文件形式:适合于返回结果较复杂的情况,例如返回一个学生的详细信息,包括姓名、性别、班级、出生日期、籍贯、家庭住址等。

本案例适合于以字符串的形式返回响应结果,读取响应结果的方法为通过xmlHttpRequest对象的responseText属性,然后将页面中id属性值为StatChart的元素的src属性的值修改为响应结果。既然是实时刷新统计,修改响应结果结束后,那还有最重要的一步,就是设置每次刷新时所请求的方法,以及每次刷新的间隔时间,时间单位为毫秒,具体代码如下:

例程5-90  代码位置:光盘\mr\5\5.6\01\JS\ajax.js

function refreshChartResponse() {

   if (xmlHttpRequest.readyState == 4) { // 判断是否已经收到服务器的完整响应

       if (xmlHttpRequest.status == 200) { // 判断服务器的响应状态是否正常

            document.getElementById("StatChart").src = xmlHttpRequest.responseText;

            window.setTimeout("refreshChartSend()", 10000);

       } else {

            if (xmlHttpRequest.status == 404) {

               window.alert("您所请求的页面路径错误!");

            } else {

               window.alert("您所请求的页面有异常!");

            }

       }

   }

}

最后编写负责处理请求的Servert。在返回响应结果时,需要通过方法setContentType()设置响应类型,如果是以字符串的形式返回,则将响应类型设置为“text/plain”,如果是以XML文件的形式返回,则将响应类型设置为“text/XML”;无论采用哪种响应类型,都要通过方法setHeader()设置为不缓存响应结果;完成响应设置后,通过out对象输出响应结果就可以了,具体代码如下:

例程5-91  代码位置:光盘\mr\5\5.6\01\src\com\mwq\servlet\RefreshChart.java

public void doGet(HttpServletRequest request, HttpServletResponse response)

       throws ServletException, IOException {

   System.out.print("------ 自动刷新,"); // 向控制台输出自动刷新标记

   JDBC jdbc = new JDBC();

   MakeSimulationData msd = new MakeSimulationData();

   msd.setJdbc(jdbc);

   msd.refresh(); // 刷新模拟数据信息

   TimeSeriesChart tsc = new TimeSeriesChart();

   tsc.setJdbc(jdbc);

   String graphURL = tsc.drawTimeSeries(); // 依据数据生成统计图片,并返回图片的浏览路径

   response.setCharacterEncoding("UTF-8"); // 设置响应的编码格式:UTF-8

   response.setContentType("text/plain"); // 设置响应的类型:字符串

   response.setHeader("Cache-Control", "no-cache"); // 设置响应的缓存方式:不缓存

   PrintWriter out = response.getWriter(); // 获得输出对象

   out.write(graphURL); // 输出响应内容:新生成统计图的浏览路径

   out.close(); 关闭输出对象

}

至此,一个典型的实时动态决策分析案例就实施完成了!

3.补充说明

在本节的案例中,因为需要返回的响应结果比较简单,所以服务器是以字符串的形式返回响应结果的,如果需要返回的响应结果比较复杂,则可以以XML文件的形式返回响应结果。

下面通过将本节案例改为以XML文件的形式返回响应结果,介绍一下如何返回和接收XML文件。有两处需要修改,分别是例程5-90和例程5-91,修改后的例程5-91的代码如下,将新生成图片的浏览路径分三部分以XML文件的形式返回:

public void doGet(HttpServletRequest request, HttpServletResponse response)

       throws ServletException, IOException {

   System.out.print("------ 自动刷新,");

   JDBC jdbc = new JDBC();

   MakeSimulationData msd = new MakeSimulationData();

   msd.setJdbc(jdbc);

   msd.refresh();

   TimeSeriesChart tsc = new TimeSeriesChart();

   tsc.setJdbc(jdbc);

   String graphURL = tsc.drawTimeSeries();

   response.setCharacterEncoding("UTF-8");

   response.setContentType("text/xml"); // 设置响应的类型:XML文件

   response.setHeader("Cache-Control", "no-cache");

   PrintWriter out = response.getWriter();

   out.write("<graph-url>"); // 起始父节点

   out.write("<web-root>/TimelyRefresh</web-root>"); // 子节点及值

   out.write("<servlet-mapping>/servlet/DisplayChart</servlet-mapping>");

   out.write("<graph-name>" + graphURL.substring(45) + "</graph-name>");

   out.write("</graph-url>"); // 终止父节点

   out.close();

}

下面是修改后的例程5-90的代码,通过逐步解析返回的XML文件,得到各元素的值,然后利用各元素的值组合新生成图片的浏览路径,并修改页面中图片的浏览路径,具体代码如下:

function refreshChartResponse() {

   if (xmlHttpRequest.readyState == 4) {

       if (xmlHttpRequest.status == 200) {

            // 获得返回的XML文件对象

            var xmlDom = xmlHttpRequest.responseXML;

            // 获得XML文件的父元素对象

            var graphUrlElement = xmlDom.documentElement;

            // 获得父元素中指定名称的子元素对象

            var webRootElement = graphUrlElement.getElementsByTagName("web-root");

            // 获得子元素对象的值

            var webRootValue = webRootElement[0].firstChild.data;

            var servletMappingElement =

                 graphUrlElement.getElementsByTagName("servlet-mapping");

            var servletMappingValue = servletMappingElement[0].firstChild.data;

            var graphNameElement =

                 graphUrlElement.getElementsByTagName("graph-name");

            var graphNameValue = graphNameElement[0].firstChild.data;

            // 组合新生成图片的浏览路径

            var graphUrl = webRootValue + servletMappingValue +

                 "?filename=" + graphNameValue;

            // 修改页面中图片的浏览路径

            document.getElementById("StatChart").src = graphUrl;

            window.setTimeout("refreshChartSend()", 10000);

       } else {

            if (xmlHttpRequest.status == 404) {

               window.alert("您所请求的页面路径错误!");

            } else {

               window.alert("您所请求的页面有异常!");

            }

       }

   }

}

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论