今天的市场,全球化程度越来越高,竞争越来越激烈,在这种情况下,企业要想占有市场的更大份额,能够继续生存和发展,必须尽量避免决策失误,因此,加强企业信息的搜集、整理和分析,就显得尤为重要,因为这是避免决策失误的前提条件。
所谓决策,就是人们为了达到一定的目标,从若干个可行的策略中选择最好策略的过程。“决策分析”是为了研究出怎样才能做出最科学的决策。在做决策分析时,通常需要对一些数据进行分析,包括利用表格和图表等形式,将分析结果清晰的表现出来,本章将详细介绍各种决策分析方案的优点和实施方法。
5.1 决策分析技术
在开发具有决策分析功能的软件时,为了能够合理的选择决策分析方案,首先要了解相关的决策分析技术,本节展现给读者的就是这些决策分析技术,通过对本节的研读,读者将对决策分析方案有一个初步的了解。
5.1.1 交叉表分析技术
当对一个数据表中的部分数据从不同的角度进行分析时,需要通过交叉表技术来实现。通过交叉表技术,可以根据数据表中的3列,透彻的分析数据表中的部分数据。在这3列中,其中的一列的非重复值作为交叉表的主键列的值,第二列的所有非重复值作为交叉表的非主键列的名称,第3列的值则为欲统计的数据。例如通过如图5.1所示数据表中的merchandise_info_id列、order_info_id列和amount列得到的交叉表如图5.2所示,其中交叉表的第二列为增加的统计列。

图5.1 数据表tb_orderForGoods

图5.2 依据表tb_orderForGoods得到的交叉表
说明:这里的交叉表技术是在SQL Server 2000数据库上测试的,在其他类型的数据库上可能需要进行相应的改动!
交叉表技术分为静态交叉表技术和动态交叉表技术,它们的区别是动态交叉表技术可以根据原数据表指定列的值自动确定新生成交叉表的列的个数和名称,而静态交叉表技术均需要人工确定。
下面来看通过静态交叉表技术获得图5.2所示交叉表的方法,完整代码如下:
SELECT merchandise_info_id,
SUM(amount) AS [SUM of amount],
SUM(CASE order_info_id WHEN 100001 THEN amount ELSE NULL END) AS [100001],
SUM(CASE order_info_id WHEN 100002 THEN amount ELSE NULL END) AS [100002],
SUM(CASE order_info_id WHEN 100003 THEN amount ELSE NULL END) AS [100003],
SUM(CASE order_info_id WHEN 100004 THEN amount ELSE NULL END) AS [100004],
SUM(CASE order_info_id WHEN 100005 THEN amount ELSE NULL END) AS [100005],
SUM(CASE order_info_id WHEN 100006 THEN amount ELSE NULL END) AS [100006]
FROM tb_orderForGoods
GROUP BY merchandise_info_id;
在SQL Server查询分析器上直接执行上面的代码,就可以得到如图5.2所示的交叉表。如果order_info_id列拥有多个不同的列值,则需要编写多个类似上面第3行的代码,所以,静态交叉表技术只适合列值固定的情况。
下面来看通过动态交叉表技术获得上述交叉表的方法,动态交叉表技术需要通过存储过程来实现,实现的大体思路是:首先通过检索指定列的信息定义一个游标,即上面的order_info_id列,然后遍历游标,用游标里的值替换在实现静态交叉表中的CASE语句中的判断内容,生成新的SQL语句,最后执行新生成的SQL语句,并返回执行结果。创建实现图5.2所示交叉表的存储过程的完整代码如下:
CREATE procedure procedure_across_table
@TableName as varchar(50), --生成交叉表依据的表名
@NewColumn as varchar(50), --生成表头依据的字段名
@GroupColumn as varchar(50), --分组依据的字段名
@StatColumn as varchar(50), --欲统计的字段名
@Operator as varchar(10) --统计的运算方式
AS
DECLARE @SQL as varchar(1000), @Column as varchar(50) --定义参数
EXECUTE ('DECLARE cursor_new_column CURSOR FOR SELECT DISTINCT ' + @NewColumn + '
from ' + @TableName + ' for read only ') --定义游标
begin
SET nocount ON
SET @SQL='select ' + @GroupColumn + ', ' + @Operator + '(' + @StatColumn + ') AS
[' + @Operator + ' of ' + @StatColumn + ']' --定义SQL语句头
OPEN cursor_new_column
while (0=0)
BEGIN --遍历游标
FETCH NEXT FROM cursor_new_column INTO @Column --通过游标获取列头信息
if (@@fetch_status<>0) break
SET @SQL = @SQL + ', ' + @Operator + '(CASE ' + @NewColumn + ' WHEN ''' + @Column + '''
THEN ' + @StatColumn + ' ELSE Null END) AS [' + @Column + ']' --循环追加SQL语句
END
SET @SQL = @SQL + ' from ' + @TableName + ' group by ' + @GroupColumn --定义SQL语句尾
EXECUTE(@SQL) --执行SQL语句
PRINT @SQL --输出SQL语句
IF @@error <>0 RETURN @@error --如果出错,则返回错误代码
CLOSE cursor_new_column --关闭游标
DEALLOCATE cursor_new_column RETURN 0 --释放游标,释放成功则返回0
end
GO
在SQL Server查询分析器上执行下面的代码,就可以得到如图5.2所示的交叉表。
procedure_across_table 'tb_orderForGoods', 'order_info_id', 'merchandise_info_id', 'amount', 'SUM'
在SQL Server查询分析器上调用存储过程时,最前面的为欲调用的存储过程的名称,后面跟随的为执行存储过程需要的参数,参数用引号括起,存储过程名称与参数之间用空格分隔,参数之间用逗号分隔。
说明:这是一个通用的存储过程,只要正确的传入生成交叉表依据的表名(@TableName),生成表头依据的字段名(@NewColumn),生成主键列依据的字段名(@GroupColumn),欲统计的字段名(@StatColumn),统计的运算方式(@Operator),就可以成功的移植到其他表上了!
5.1.2 透视表分析技术
相信能够熟练运用Excel的人都知道它的透视表功能,通过该功能,可以完成对数据的筛选、排序和分类汇总等工作。所谓透视表,实际上就是一个三维数据表格(Multi-dimension table),让数据沿三个不同的坐标轴排列,当试图研究不同数据之间的关系时,透视表使用起来非常方便,通过它可以从不同角度对数据进行分析,从而为决策者提供浓缩信息作为参考。
图5.4是在Excel中通过图5.3所示数据表建立的透视表。

图5.3 Excel中的数据表

图5.4 Excel中的透视表效果
从图5.4可以看出,透视表共包含5个部分:
(1)页字段:用来查看透视表当前页显示的数据范围;
(2)行字段:用来查看透视表显示的数据行;
(3)列字段:用来查看透视表显示的数据列;
(4)下拉式字段选择菜单:用来控制透视表当前页显示的数据范围、显示的数据行和数据列;
(5)数据字段:用来查看通过透视表得到的浓缩数据。
当单击与页字段对应的下拉式字段选择菜单时,将弹出如图5.5所示的对话框,供选择当前页显示数据的范围。

图5.5 设置页字段
当单击与行字段对应的下拉式字段选择菜单时,将弹出如图5.6所示的对话框,供选择当前页显示的数据行。

图5.6 设置行字段
当单击与列字段对应的下拉式字段选择菜单时,将弹出如图5.7所示的对话框,供选择当前页显示的数据列。

图5.7 设置列字段
从此可以看出,透视表是交叉表的高级形式,提供了更强大的统计分析功能,更灵活的数据筛选方式,更方便的表格内容切换功能。
如果想实现上述功能,关键是开发出一个合理的存储过程,可以通过修改实现动态交叉表的存储过程实现。
实现透视表的存储过程procedure_clairvoyant_table,需要添加几个入口参数,分别用来传入页字段、行字段和列字段需要显示的数据,当为空时则显示全部,实现透视表的存储过程的入口参数如下。
@TableName as varchar(50), --实现透视表依据的表名
@PageFieldByColumn as varchar(50), --页字段依据的列名
@PageFieldValue as varchar(50), --用来控制透视表页字段的数据
@RowFieldByColumn as varchar(50), --行字段依据的列名
@RowFieldValue as varchar(200), --用来控制透视表行字段的数据
@ColumnFieldByColumn as varchar(50), --列字段依据的列名
@ColumnFieldValue as varchar(200), --用来控制透视表列字段的数据
@DataFieldByColumn as varchar(50), --数据字段依据的列名
@DataFieldOperateMethod as varchar(10) --对数据字段的统计方式
下面的代码负责定义在后面需要用到的几个参数。
DECLARE @SQL as varchar(2000), @ColumnName as varchar(100), @PageFieldData as
varchar(200), @RowFieldData as varchar(200), @ColumnFieldData as varchar(200)
下面的代码负责判断传入的页字段、行字段和列字段的值是否为空,并根据不同情况生成相应的SQL语句,并赋值给前面定义的相应的参数。
if(@PageFieldValue='')
set @PageFieldData=@TableName
else
set @PageFieldData='(select * from '+@TableName+' where '+@PageFieldByColumn
+'='''+@PageFieldValue+''')'
if(@RowFieldValue='')
set @RowFieldData=''
else
set @RowFieldData='where PageFieldData.'+@RowFieldByColumn+' in('
+@RowFieldValue+')'
if(@ColumnFieldValue='')
set @ColumnFieldData=''
else
set @ColumnFieldData=' where '+@ColumnFieldByColumn+' in ('+@ColumnFieldValue+')'
下面的代码负责生成游标,在生成游标时,将用到参数ColumnFieldData。
EXECUTE ('DECLARE cursor_column_field CURSOR FOR SELECT DISTINCT ' + @ColumnFieldByColumn
+ ' from ' + @TableName + @ColumnFieldData + ' for read only') --定义游标
下面的代码通过遍历游标,控制生成SQL语句,这里将用到其他的几个参数。
SET @SQL='select PageFieldData.' + @RowFieldByColumn +', ' --定义SQL语句头
OPEN cursor_column_field
while (0=0)
BEGIN --遍历游标
FETCH NEXT FROM cursor_column_field INTO @ColumnName --通过游标获取列头信息
if (@@fetch_status<>0)
break
SET @SQL = @SQL + @DataFieldOperateMethod + '(CASE ' + @ColumnFieldByColumn
+ ' WHEN ''' + @ColumnName + ''' THEN ' + @DataFieldByColumn + ' ELSE Null END)
AS [' + @ColumnName + '], ' --循环追加SQL语句
END
SET @SQL = @SQL + @DataFieldOperateMethod + '(' + @DataFieldByColumn + ') AS ['
+ @DataFieldOperateMethod + ' of ' + @DataFieldByColumn + '] from
' + @PageFieldData + ' as PageFieldData ' + @RowFieldData
+ ' group by PageFieldData.' + @RowFieldByColumn --定义SQL语句尾
下面还需要开发一个存储过程procedure_clairvoyant_table_column_stat,用来实现透视表最后一行的总计功能,只需在上面最后一段代码中做简单的修改,去掉根据行字段依据列的聚集代码,修改后的代码如下。
SET @SQL='select ' --定义SQL语句头
OPEN cursor_column_field
while (0=0)
BEGIN --遍历游标
FETCH NEXT FROM cursor_column_field INTO @ColumnName --通过游标获取列头信息
if (@@fetch_status<>0)
break
SET @SQL = @SQL + @DataFieldOperateMethod + '(CASE ' + @ColumnFieldByColumn
+ ' WHEN ''' + @ColumnName + ''' THEN ' + @DataFieldByColumn + ' ELSE Null END)
AS [' + @ColumnName + '], ' --循环追加SQL语句
END
SET @SQL = @SQL + @DataFieldOperateMethod + '(' + @DataFieldByColumn + ') AS ['
+ @DataFieldOperateMethod + ' of ' + @DataFieldByColumn + '] from
' + @PageFieldData + ' as PageFieldData ' + @RowFieldData --定义SQL语句尾
注意:在调用存储过程生成透视表时,列字段的非重复值不能太多,否则通过存储过程生成的SQL语句将超出最大长度,从而抛出异常!
5.1.3 统计图分析技术
所谓统计图分析技术,就是将统计结果以统计图的形式展现给用户,常用的统计图有柱形图、饼形图、折线图、区域图和时序图,JFreeChart对上述统计图提供了完美的实现。JFreeChart是一个Java开源项目,是一款优秀的用来生成Java图表的插件,提供了在Java Application、Servlet和JSP下生成各种图片格式的图表。
1.基本配置
在JFreeChart的官方网站(http://www.jfree.org/jfreechart/index.html)上可以下载到该插件,该插件有两个版本:
l jfreechart-1.0.6.zip,该版本适用于Windows系统。
l jfreechart-1.0.6.tar.gz,该版本适用于UNIX / Linux系统。
本书所有案例的开发环境均为Windows系统,解压缩jfreechart-1.0.6.zip后将得到一个名为jfreechart-1.0.6的文件夹,只需将lib子文件夹内的如下文件拷贝到WEB应用程序的/WEB-INF/lib文件夹内:
l jfreechart-1.0.5.jar
l jcommon-1.0.10.jar
l junit.jar
l gnujaxp.jar
l servlet.jar
并且在/WEB-INF/web.xml文件中添加如下代码,就可以利用JFreeChart插件生成统计图表了。
<servlet>
<servlet-name>DisplayChart</servlet-name>
<servlet-class>org.jfree.chart.servlet.DisplayChart</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DisplayChart</servlet-name>
<url-pattern>/servlet/DisplayChart</url-pattern>
</servlet-mapping>
2.开发思路
在利用JFreeChart插件生成统计图表时,大体有两种开发思路,一种是通过工厂类ChartFactory创建JFreeChart实例,另一种是通过JFreeChart类创建JFreeChart实例。
在通过工厂类ChartFactory创建JFreeChart实例时,基本的开发思路如下:
(1)创建相应统计图的数据集实例。
(2)通过工厂类ChartFactory创建JFreeChart实例,ChartFactory类中的所有方法均需要传入一个数据集实例。
(3)订制图片和绘图区的绘制属性,该步可选。
(4)生成指定格式的图片,并返回生成图片的名称。
(5)组织图片浏览路径。
(6)通过HTML中的<img>元素显示图片。
在通过JFreeChart类创建JFreeChart实例时,基本的开发思路如下:
(1)创建相应统计图的绘图区实例;
(2)创建相应统计图的数据集实例,并传入绘图区实例;
(3)订制绘图区的绘制属性,例如绘图区的背景色,柱形图坐标轴的绘制属性,饼形图图例的填充色等,该步可选;
(4)通过JFreeChart类创建JFreeChart实例,JFreeChart类的所有构造方法均需要传入一个绘图区实例;
(5)订制图片的绘制属性,例如图片的标题、背景色等,该步可选;
(6)生成指定格式的图片,并返回生成图片的名称;
(7)组织图片浏览路径;
(8)通过HTML中的<img>元素显示图片。
3.核心API简介
在使用JFreeChart插件之前,先了解一下该插件的核心类及其功能,这对将来能够得心应手的使用该插件是非常重要的,JFreeChart核心类及其功能请参见表5.1。
表5.1 JFreeChart核心类及其功能
|
类名 |
功能 |
|
JFreeChart |
图表对象。生成任何类型的图表都要通过该对象,JFreeChart插件提供了一个工厂类ChartFactory,用来创建各种类型的图表对象 |
|
XXXDataset |
数据集对象。用来保存绘制图表的数据,不同类型的图表对应着不同类型的数据集对象 |
|
XXXPlot |
绘图区对象。如果需要自行定义绘图区的相关绘制属性,需要通过该对象进行设置 |
|
XXXAxis |
坐标轴对象。用来定义坐标轴的绘制属性 |
|
XXXRenderer |
图片渲染对象。用于渲染和显示图表 |
|
XXXURLGenerator |
链接对象。用于生成Web图表中项目的鼠标单击链接 |
|
XXXToolTipGenerator |
图表提示对象。用于生成图表提示信息,不同类型的图表对应着不同类型的图表提示对象 |
通过工厂类ChartFactory,可以创建各种类型的图表对象,常用的创建JFreeChart实例的方法及其功能请参见表5.2。
表5.2 ChartFactory类中常用方法及其功能
|
名称 |
功能 |
|
createBarChart()和createBarChart3D() |
分别用来创建绘制普通柱形图和3D柱形图的JFreeChart实例,它们基于的是DefaultCategoryDataset类型的数据集 |
|
createXYBarChart() |
用来创建绘制普通柱形图的JFreeChart实例,它基于的是TimeSeries类型的数据集,TimeSeries数据集主要用来绘制与日期和时间相关的统计图 |
|
createStackedBarChart()和createStackedBarChart3D() |
它们同createBarChart()和createBarChart3D()的功能相同,只是绘制出的柱形图效果不同,它们可以互换使用 |
|
createPieChart()和createPieChart3D() |
分别用来创建绘制普通饼形图和3D饼形图的JFreeChart实例,它们基于的是DefaultPieDataset类型的数据集 |
|
createLineChart()和createLineChart3D() |
分别用来创建绘制普通折线图和3D折线图的JFreeChart实例,它们基于的是DefaultCategoryDataset类型的数据集 |
|
createXYLineChart() |
用来创建绘制普通折线图的JFreeChart实例,它基于的是TimeSeries类型的数据集,TimeSeries数据集主要用来绘制与日期和时间相关的统计图 |
|
createAreaChart() |
用来创建绘制普通区域图的JFreeChart实例,它基于的是DefaultCategoryDataset类型的数据集 |
|
createXYAreaChart() |
用来创建绘制普通区域图的JFreeChart实例,它基于的是TimeSeries类型的数据集,TimeSeries数据集主要用来绘制与日期和时间相关的统计图 |
|
createTimeSeriesChart() |
用来创建绘制普通时序图的JFreeChart实例,时序图与折线图有些类似,不过时序图提供了绘制移动平均线的功能,通过给定的数据集实例,可以自动计算任意时间段的移动平均值,它基于的是TimeSeries类型的数据集,TimeSeries数据集主要用来绘制与日期和时间相关的统计图 |
注意:ChartFactory类中的所有方法均需要传入一个数据集实例,并且返回值类型均为JFreeChart!
如果是通过工厂类ChartFactory创建JFreeChart实例,可以通过ChartFactory类提供的方法获得绘图区实例;如果是通过JFreeChart类创建JFreeChart实例,则需要在创建JFreeChart实例之前订制好绘图区实例,然后在创建时传入。常用的绘图区类及其功能请参见表5.3。
表5.3 常用的绘图区类及其功能
|
名称 |
功能 |
|
CategoryPlot |
在绘制基于DefaultCategoryDataset数据集的柱形图、折线图、区域图时,绘图区为该类型 |
|
PiePlot |
在绘制普通饼形图时,绘图区为该类型 |
|
PiePlot3D |
在绘制3D饼形图时,绘图区为该类型 |
|
XYPlot |
在绘制基于TimeSeries数据集的柱形图、折线图、区域图时,绘图区为该类型 |
表5.3中介绍的几个绘图区类均继承于Plot类,Plot类提供的经常用来订制绘图区绘制属性的方法及其功能请参见表5.4。
表5.4 Plot类提供的常用方法及其功能
|
名称 |
功能 |
|
setBackgroundPaint(Paint paint) |
用来设置绘图区的背景色 |
|
setBackgroundAlpha(float alpha) |
用来设置绘图区背景的透明度,参数在0.0和1.0之间,数值越大透明度越低 |
|
setForegroundAlpha(float alpha) |
用来设置绘图区前景的透明度,参数在0.0和1.0之间,数值越大透明度越高 |
|
setNoDataMessage(String message) |
用来设置在没有绘图数据时在绘图区显示的提示信息 |
|
setNoDataMessageFont(Font font) |
用来设置没有绘图数据时显示的提示信息的字体 |
|
setNoDataMessagePaint(Paint paint) |
用来设置没有绘图数据时显示的提示信息的颜色 |
CategoryPlot类提供的经常用来订制绘图区绘制属性的方法及其功能请参见表5.5。
表5.5 CategoryPlot类提供的常用方法及其功能
|
名称 |
功能 |
|
setDataset(CategoryDataset dataset)和setDataset(int, CategoryDataset) |
均用来设置绘图数据集实例,后者的第一个参数为数据集的唯一标识值,前者是采用默认标识值(0)。如果在一个绘图区中只包含一个分类轴和一个数值轴,建议使用前者;否则,一定要通过后者为每个数据集实例指定一个唯一标识值 |
|
setDomainAxis(CategoryAxis axis) |
用来设置分类轴实例 |
|
setDomainAxisLocation(AxisLocation location) |
用来设置分类轴的绘制位置,入口参数常量在org.jfree.chart.axis.AxisLocation类中做了定义 |
|
setDomainGridlinesVisible(boolean visible) |
用来设置分类轴标记线是否可见,默认为不可见(false) |
|
setDomainGridlineStroke(Stroke stroke) |
用来设置分类轴标记线的绘制风格 |
|
setDomainGridlinePaint(Paint paint) |
用来设置分类轴标记线的颜色 |
|
setRangeAxis(ValueAxis axis) |
用来设置数据轴实例 |
|
setRangeAxisLocation(AxisLocation location) |
用来设置数据轴的绘制位置,入口参数常量在org.jfree.chart.axis.AxisLocation类中做了定义 |
|
setRangeGridlinesVisible(boolean visible) |
用来设置数据轴标记线是否可见,默认为可见(true) |
|
setRangeGridlineStroke(Stroke stroke) |
用来设置数据轴标记线的绘制风格 |
|
setRangeGridlinePaint(Paint paint) |
用来设置数据轴标记线的颜色 |
|
mapDatasetToDomainAxis(int, int) |
用来将指定标识值的绘图数据集与分类轴建立关联 |
|
mapDatasetToRangeAxis(int, int) |
用来将指定标识值的绘图数据集与数据轴建立关联 |
PiePlot类提供的经常用来订制绘图区绘制属性的方法及其功能请参见表5.6。
表5.6 PiePlot类提供的常用方法及其功能
|
名称 |
功能 |
|
setCircular(boolean flag) |
用来设置饼图为正圆还是椭圆,默认为正圆(true)。建议在绘制普通饼图时采用正圆,在绘制3D饼图时采用椭圆 |
|
setStartAngle(double angle) |
用来设置饼图第一段圆弧的起始绘制角度,默认为在饼图的正上方开始绘制。水平方向饼图的最左侧为0度,最右侧为180度;垂直方向饼图的正上方为90度,正下方为270度 |
|
setDirection(Rotation direction) |
用来设置饼图的绘制方向,默认为按顺时针方向绘制。Rotation.CLOCKWISE代表顺时针,Rotation.ANTICLOCKWISE代表逆时针 |
|
setLegendLabelGenerator(PieSectionLabelGenerator generator) |
用来设置饼图中图例的输出样式 |
|
setLabelGenerator(PieSectionLabelGenerator generator) |
用来设置饼图中普通标签的输出样式,当设置为NULL时,则不显示普通标签及连接线 |
|
setLabelFont(Font font) |
用来设置饼图中普通标签的字体样式 |
|
setLabelPaint(Paint paint) |
用来设置饼图中普通标签的字体颜色 |
|
setLabelBackgroundPaint(Paint paint) |
用来设置饼图中普通标签的背景颜色 |
|
setLabelOutlinePaint(Paint paint) |
用来设置饼图中普通标签的边框颜色 |
|
setLabelLinkPaint(Paint paint) |
用来设置饼图中普通标签与圆弧之间连接线的颜色 |
|
setSectionPaint(Comparable, Paint) |
用来设置饼图中代表指定图例的扇形的填充色 |
|
setToolTipGenerator(PieToolTipGenerator generator) |
用来设置热点饼图中热区标签的输出样式 |
|
setURLGenerator(PieURLGenerator generator) |
用来设置热点饼图中热区链接的URL |
|
setIgnoreNullValues(boolean flag) |
用来设置是否显示绘图数据设为NULL的图例,默认为显示(false) |
|
setIgnoreZeroValues(boolean flag) |
用来设置是否显示绘图数据设为0的图例,默认为显示(false) |
PiePlot3D类仅提供了一个用来设置3D饼图Z轴高度的方法setDepthFactor(double factor)。
XYPlot类提供的经常用来订制绘图区绘制属性的方法及其功能请参见表5.7。
表5.7 XYPlot类提供的常用方法及其功能
|
名称 |
功能 |
|
setDataset(CategoryDataset dataset)和setDataset(int, CategoryDataset) |
均用来设置绘图数据集实例,后者的第一个参数为数据集的唯一标识值,前者是采用默认标识值(0)。如果在一个绘图区中只包含一个分类轴和一个数值轴,建议使用前者;否则,一定要通过后者为每个数据集实例指定一个唯一标识值 |
|
setDomainAxis(CategoryAxis axis) |
用来设置分类轴实例 |
|
setDomainAxisLocation(AxisLocation location) |
用来设置分类轴的绘制位置,入口参数常量在org.jfree.chart.axis.AxisLocation类中做了定义 |
|
setDomainGridlinesVisible(boolean visible) |
用来设置分类轴标记线是否可见,默认为不可见(false) |
|
setDomainGridlineStroke(Stroke stroke) |
用来设置分类轴标记线的绘制风格 |
|
setDomainGridlinePaint(Paint paint) |
用来设置分类轴标记线的颜色 |
|
setRangeAxis(ValueAxis axis) |
用来设置数据轴实例 |
|
setRangeAxisLocation(AxisLocation location) |
用来设置数据轴的绘制位置,入口参数常量在org.jfree.chart.axis.AxisLocation类中做了定义 |
|
setRangeGridlinesVisible(boolean visible) |
用来设置数据轴标记线是否可见,默认为可见(true) |
|
setRangeGridlineStroke(Stroke stroke) |
用来设置数据轴标记线的绘制风格 |
|
setRangeGridlinePaint(Paint paint) |
用来设置数据轴标记线的颜色 |
|
mapDatasetToDomainAxis(int, int) |
用来将指定标识值的绘图数据集与分类轴建立关联 |
|
mapDatasetToRangeAxis(int, int) |
用来将指定标识值的绘图数据集与数据轴建立关联 |
可以通过绘图区实例获得坐标轴实例,然后设置坐标轴的绘制属性;也可以将设置好的坐标轴实例传入到绘图区实例中。常用的坐标轴类及其功能请参见表5.8。
表5.8 常用的坐标轴类及其功能
|
名称 |
功能 |
|
CategoryAxis |
用来定义分类型坐标轴 |
|
ValueAxis |
用来定义数值型坐标轴,包括普通的数值型和日期型 |
|
NumberAxis |
用来定义普通数值型坐标轴 |
|
DateAxis |
用来定义日期型坐标轴 |
Axis类是表5.8中介绍的几个类的父类,Axis类提供的经常用来订制绘图区绘制属性的方法及其功能请参见表5.9。
表5.9 Axis类提供的常用方法及其功能
|
名称 |
功能 |
|
setLabel(String label) |
用来设置坐标轴标题 |
|
setLabelFont(Font font) |
用来设置坐标轴标题的字体 |
|
setLabelPaint(Paint paint |
用来设置坐标轴标题的颜色 |
|
setLabelAngle(double angle) |
用来设置坐标轴标题的旋转角度 |
|
setTickLabelFont(Font font) |
用来设置坐标轴标尺值的字体 |
|
setTickLabelPaint(Paint paint) |
用来设置坐标轴标尺值的颜色 |
|
setTickMarkStroke(Stroke stroke) |
用来设置坐标轴标尺标记的笔触 |
|
setTickMarkPaint(Paint paint) |
用来设置坐标轴标尺标记的颜色 |
CategoryAxis类提供的经常用来订制绘图区绘制属性的方法及其功能请参见表5.10。
表5.10 CategoryAxis类提供的常用方法及其功能
|
名称 |
功能 |
|
setLowerMargin(double margin) |
用来设置分类轴的下边距 |
|
setUpperMargin(double margin) |
用来设置分类轴的上边距 |
|
setCategoryMargin(double margin) |
用来设置分类轴之间的间距 |
|
setMaxCategoryLabelWidthRatio(float ratio) |
用来设置显示分类轴标记内容的最大比例,如果设为1,表示可以显示标记内容的最大长度与绘图所占宽度相同 |
ValueAxis类是NumberAxis类和DateAxis类的父类,ValueAxis类提供的经常用来订制绘图区绘制属性的方法及其功能请参见表5.11。
表5.11 ValueAxis类提供的常用方法及其功能
|
名称 |
功能 |
|
setFixedAutoRange(double length) |
用来动态设置数据轴的标尺范围。例如设置入口参数为100,表示数据轴的标尺范围为从(MaxValue-100)到(MaxValue) |
|
setLowerBound(double min) |
用来设置数据轴标尺值的最小值 |
|
setUpperBound(double max) |
用来设置数据轴标尺值的最大值 |
|
setVerticalTickLabels(boolean flag) |
用来设置日期轴标记值是否垂直显示,默认为水平显示(false) |
NumberAxis类提供的经常用来订制绘图区绘制属性的方法及其功能请参见表5.12。
表5.12 NumberAxis类提供的常用方法及其功能
|
名称 |
功能 |
|
setNumberFormatOverride(NumberFormat formatter) |
用来简单格式化数据轴标尺值的输出样式 |
|
setTickUnit(NumberTickUnit unit) |
即可以格式化数据轴标尺值的输出样式,又可以设置标尺值之间的间隔 |
DateAxis类提供的经常用来订制绘图区绘制属性的方法及其功能请参见表5.13。
表5.13 DateAxis类提供的常用方法及其功能
|
名称 |
功能 |
|
setDateFormatOverride(DateFormat formatter) |
用来简单格式化日期轴标尺值的输出样式 |
|
setTickUnit(DateTickUnit unit) |
即可以格式化日期轴标尺值的输出样式,又可以设置标尺值之间的间隔 |
通过上面对JFreeChart常用类及方法的研究,就可以利用JFreeChart插件绘制出漂亮的统计图表了。
5.1.4 实时动态决策分析与Ajax技术
既然是实时动态决策分析,就要求软件展示给用户的统计数据始终是最新的,这就要求软件能够自动的刷新统计数据,并及时的展示给用户,而传统的JSP页面,用户每发出一次请求,或者定时刷新页面的部分内容,都需要一个等待的过程(白屏或者光标变成沙漏),直到服务器返回响应结果。在这期间,服务器完成了一系列的工作,包括接收请求、处理请求和返回处理结果,而对于用户来说却不能做任何事情,因为浏览器一直在等待返回的处理结果,并且在得到返回结果后还需要一个重新绘制页面的过程,从而导致每次请求都会出现页面抖动的效果,这对浏览者来说是很不舒服的,如果请求等待的时间过长,用户很有可能放弃这次请求,所以,通过传统的JSP技术,开发基于Web的实时检测系统是件很痛苦的事情。
在这里,引入了Ajax技术,Ajax技术解决了上述的问题,实现了页面的无闪烁刷新。Ajax是“Asynchronous Javascript and XML”的简称,即异步Javascript和XML,它并不是一门新的语言或技术,它实际上是将几项技术按一定的方式组合在一起,在共同的协作中发挥各自的作用,这些技术包括XHTML、CSS、Javascript、DOM、XML、XSTL和XMLHttpRequest,在Ajax中,各种技术各司其职:
l 使用XHTML和CSS进行数据的标准化显示;
l 使用DOM实现动态显示和交互;
l 使用XML和XSTL进行数据的交换与处理;
l 使用XMLHttpRequest对象进行异步数据读取;
l 使用Javascript绑定和处理所有数据;
在Ajax技术提出之前,对于上述技术都只是单独的使用,或是简单地组合使用,而没有真正意义上的综合应用。
运用了Ajax技术的Web应用模型,它的工作原理相当于在客户端和服务器端之间添加了一个中间层,称为Ajax引擎,它使用户操作与服务器响应异步化。在这种模式下,用户的请求首先交给Ajax引擎,其中的部分请求,如数据验证和简单的数据处理等由Ajax引擎直接完成,只有那些确实需要由服务器来完成的请求,才由Ajax引擎代为向服务器提交,引入Ajax的Web模型与传统的Web模型的区别如图5.8所示。

图5.8 传统Web应用模型与Ajax Web应用模型的区别
Ajax引擎有狭义和广义之分,广义的Ajax引擎,包括了狭义的Ajax引擎和一些由Javascript写成的业务逻辑模块;而狭义的Ajax引擎,只是一些与XMLHttpRequest对象相关的、用来完成与服务器交互的模块,这里主要介绍狭义的Ajax引擎,以下简称Ajax引擎。
Ajax引擎的主要功能包括:
(1)捕获浏览器事件
当浏览器中的Html文档或其中的某些元素被触发时,Web浏览器就会产生一个事件。例如,当浏览器加载完一个Html文档,就会产生一个onload事件;当用鼠标单击按钮,就会产生一个onclick事件;当按下一个键盘键,就会产生一个keydown事件。要捕获浏览器的某个事件,就是为该事件注册一个处理函数。例如<input type="button" name="photo" value="修改" onclick="updatePhoto()">,就是为按钮注册了一个鼠标单击的处理函数updatePhoto(),当鼠标单击这个按钮时,就会执行updatePhoto()。
(2)初始化XMLHttpRequest对象
在捕获了用户的交互事件之后,如果需要与服务器交互,就要使用XMLHttpRequest对象。但是,对于不同的浏览器或者不同的版本,实例化XMLHttpRequest对象的过程是不同的。IE以ActiveX控件的形式提供,而Mozilla等浏览器则以XMLHttpRequest类的形式提供,所以需要保证程序的兼容性,实现程序的跨浏览器运行。
(3)向服务器发送请求
在得到一个已经实例化的XMLHttpRequest对象之后,就可以向服务器发送HTTP请求了,在发送HTTP请求之前,需要先指定一个响应处理函数,即服务器响应之后的回调函数,指定方法是将XMLHttpRequest对象的onreadystatechange属性的值设置为欲调用函数的名称,在函数的名称后不可以带有括号“()”。例如XMLHttpRequest.onreadystatechange = processResponse。设置完回调函数之后,再依次调用XMLHttpRequest对象的open和send方法,一个HTTP请求就成功发送到服务器了。
(4)接收服务器响应
当服务器处理完HTTP请求之后,会调用前面设置的回调函数。回调函数第一步要做的是检查XMLHttpRequest对象的readyState属性的值,判断HTTP请求目前的状态。当readyState属性的值为4时,表示服务器已经返回处理信息。确认服务器已经返回处理信息后,还要检查返回的HTTP状态码,即XMLHttpRequest对象的status属性的值,目的是判断服务器对请求的处理结果是否正常,如果不能正确处理HTTP请求,将返回错误信息。当status属性的值为200(所有的HTTP状态码都可以在W3C的官方网站上查到)时,表示处理结果正常。在这种情况下,就可以处理返回的数据了。
(5)更新浏览器的页面内容
对于成功处理HTTP请求返回的结果,XMLHttpRequest对象有两种处理方式:
l responseText:将返回的信息当字符串使用。一些状态信息等非结构化的数据,例如修改成功等可以利用该方式进行处理。
l responseXML:将返回的信息当XML文档使用,需要通过DOM进行解析处理。一些结构化的数据,如一页中的20条记录,可以利用该方式进行处理。
上面依次列出的Ajax引擎的功能,也是Ajax与服务器的交互过程,从这个交互过程中可以看出,Ajax引擎依然遵循request→response模式,不同的是这个过程是异步的。






