`
sarin
  • 浏览: 1748016 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
E3b14d1f-4cc5-37dd-b820-b6af951740bc
Spring数据库访问系列...
浏览量:172816
C2083dc5-6474-39e2-993e-263652d27795
Android学习笔记
浏览量:366549
5f40a095-b33c-3e8e-8891-606fcf3b8d27
iBatis开发详解
浏览量:188303
B272a31d-e7bd-3eff-8cc4-c0624ee75fee
Objective-C学习...
浏览量:98739
社区版块
存档分类
最新评论

使用Fusion Charts制作报表(dom4j生成XML)

阅读更多
    首次看到Fusion Charts是在Bug Free上,有个统计功能,看到了这个数据报表,也是Flash实现的,和Open Flash Chart类似,但是数据格式完全不同。OFC使用JSON数据,而Fusion Chart使用XML数据,OFC是单文件的,而FC是多文件(不同的Flash显示不同类型的报表)。Fusion Charts的官方网站是http://www.fusioncharts.com/free ,可以下载开发包和查看示例。下载Fusion Charts Free后的开发包内有swf文件,示例代码和支持的JS文件。我们只要swf和js即可,开发环境自行搭建,非常简单,注意这里我们使用免费的Fusion Charts Free。
    因为Fusion Charts的数据源是XML格式,那么就要准备生成XML的API,这有很多选择,如JDOM,DOM4J都不错。因为Hibernate默认只用了Dom4J来解析XML,那么为了避免过多引入JAR依赖,就使用Dom4j来生成XML文本。下面先对Dom4j做个初步的封装,使得使用起来方便一些。
package org.xxx.core.util;

import java.io.IOException;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
/**
 * 使用dom4j生成XML工具类
 * 
 * @author Sarin
 * 
 */
public class XMLUtil {
	private Document document = null;

	public Document getDocument() {
		return document;
	}
	/**
	 * 构造方法,初始化Document
	 */
	public XMLUtil() {
		document = DocumentHelper.createDocument();
	}
	/**
	 * 生成根节点
	 * 
	 * @param rootName
	 * @return
	 */
	public Element addRoot(String rootName) {
		Element root = document.addElement(rootName);
		return root;
	}
	/**
	 * 生成节点
	 * 
	 * @param parentElement
	 * @param elementName
	 * @return
	 */
	public Element addNode(Element parentElement, String elementName) {
		Element node = parentElement.addElement(elementName);
		return node;
	}
	/**
	 * 为节点增加一个属性
	 * 
	 * @param thisElement
	 * @param attributeName
	 * @param attributeValue
	 */
	public void addAttribute(Element thisElement, String attributeName,
			String attributeValue) {
		thisElement.addAttribute(attributeName, attributeValue);
	}
	/**
	 * 为节点增加多个属性
	 * 
	 * @param thisElement
	 * @param attributeNames
	 * @param attributeValues
	 */
	public void addAttributes(Element thisElement, String[] attributeNames, String[] attributeValues) {
		for (int i = 0; i < attributeNames.length; i++) {
			thisElement.addAttribute(attributeNames[i], attributeValues[i]);
		}
	}
	/**
	 * 增加节点的值
	 * 
	 * @param thisElement
	 * @param text
	 */
	public void addText(Element thisElement, String text) {
		thisElement.addText(text);
	}
	/**
	 * 获取最终的XML
	 * 
	 * @return
	 * @throws IOException
	 */
	public String getXML() {
		return document.asXML().substring(39);
	}
}

    获取的XML因为包含声明,而Fusion Chart中不需要,所以这里就从根标记处开始截取。下面来看看Fusion Chart解析XML的格式。取自官方网站的一个示例:
<graph  yAxisName='Sales Figure'  caption='Top 5 Sales Person'  numberPrefix='$' decimalPrecision='1'  divlinedecimalPrecision='0' limitsdecimalPrecision='0'>
        <set name='Alex' value='25000' color='AFD8F8'/> 
<set name='Mark' value='35000' color='F6BD0F'/>
<set name='David' value='42300' color='8BBA00'/>
<set name='Graham' value='35300' color='FF8E46'/>
<set name='John' value='31300' color='008E8E'/>
</graph>

    根标记是graph,其中有可配置的属性,可以参考官方文档,这里不详细列出了。单分类报表中使用set子标记作为数据,下面来看一个具体的数据源生成方法,使用了Struts2作为Web框架来处理请求。
package org.xxx.app.action;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Element;
import org.xxx.core.util.XMLUtil;

public class ChartAction extends BaseAction {
	private String xmlStr;

	public String getXmlStr() {
		return xmlStr;
	}
	public String chart() throws Exception {
		XMLUtil xml = new XMLUtil();
		Element graph = xml.addRoot("graph");
		xml.addAttribute(graph, "caption", "访问统计");
		xml.addAttribute(graph, "subCaption", "浏览器类型统计");
		xml.addAttribute(graph, "basefontsize", "12");
		xml.addAttribute(graph, "xAxisName", "浏览器类型");
		xml.addAttribute(graph, "decimalPrecision", "0");// 小数精确度,0为精确到个位
		xml.addAttribute(graph, "showValues", "0");// 在报表上不显示数值
		List browserList = getServMgr().getChartService().getStatsByType("browser");
		for (int i = 0; i < browserList.size(); i++) {
			Map item = (HashMap) browserList.get(i);
			Element set = xml.addNode(graph, "set");
			set.addAttribute("name", (String) item.get("statVar"));
			set.addAttribute("value", item.get("statCount").toString());
			set.addAttribute("color", Integer.toHexString(
					(int) (Math.random() * 255 * 255 * 255)).toUpperCase());
		}
		xmlStr = xml.getXML();
		return "chart";
	}
}

    数据的获取使用了Spring的JdbcTemplate来进行,方法如下:
	private static final String SQL_GET_STATS = "select statVar,statCount from stats where statType=?";
	public List getStatsByType(String type) {
		return jt.queryForList(SQL_GET_STATS, new Object[] { type });
}

    数据表的结构可以参考http://sarin.iteye.com/admin/blogs/685354这篇,因为相同的演示,就用了同一个表结构。获取到数据遍历之后,就要在页面进行输出显示了,也很简单,页面如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Fusion Chart Test</title>
<script type="text/javascript" src="${base}/js/FusionCharts.js"></script>
</head>
<body>
<div id="chartDiv"></div>
<script type="text/javascript">
	var chart = new FusionCharts("${base}/charts/FCF_Column3D.swf", "0", "800", "600");
	chart.setDataXML('${xmlStr}');
	chart.render('chartDiv');
	</script>	

</body>
</html>

    使用setDataXML()方法获取传递过来的xmlStr,就是我们需要的XML数据。简单的报表这样就可以了。如果是多类别报表,只是在XML格式上有所不同,参考官方示例,重新编写XML即可。下面来看看生成的报表,非常的不错。

    希望对使用者有用,欢迎交流。
  • 大小: 39.5 KB
35
4
分享到:
评论
29 楼 sjxinrui 2014-04-22  
rzg813 写道
wolg_001 写道
请问下你用的是dom4j的哪个版本吧的包? 我的getServMgr() 为什么不能找到?

兄弟啊,那个是通过hibernate去数据库中的数据方法,跟包没有关系的!



以前我年幼无知=-=
28 楼 rzg813 2013-06-07  
wolg_001 写道
请问下你用的是dom4j的哪个版本吧的包? 我的getServMgr() 为什么不能找到?

兄弟啊,那个是通过hibernate去数据库中的数据方法,跟包没有关系的!
27 楼 sarin 2012-12-26  
chaizp 写道
我用的FusionCharts是3.1版的。
直接一句String chartHTMLCode=createChartHTML("FusionCharts/Doughnut3D.swf", "data.xml", "", "myFirst", 600, 300, false);就可以了
我也是访问数据库dom4j自动生成xml文件。
但我这里生成xml后页面不能马上加载,必须刷新下工程把xml文件刷出来才可以在页面看到数据。你这有这种问题吗?或有解决方法吗??

感觉XML没有同时加载过来,可以跟踪一下JS
26 楼 chaizp 2012-12-24  
我用的FusionCharts是3.1版的。
直接一句String chartHTMLCode=createChartHTML("FusionCharts/Doughnut3D.swf", "data.xml", "", "myFirst", 600, 300, false);就可以了
我也是访问数据库dom4j自动生成xml文件。
但我这里生成xml后页面不能马上加载,必须刷新下工程把xml文件刷出来才可以在页面看到数据。你这有这种问题吗?或有解决方法吗??
25 楼 sarin 2012-03-29  
sjxinrui 写道
能否新手向一点

就在spring里配置一个service bean而已啊,适合自己就行了
24 楼 sjxinrui 2012-03-29  
能否新手向一点
23 楼 sjxinrui 2012-03-29  
lz 你封装的那个方法我们该肿么办。。。不会弄啊
22 楼 sjxinrui 2012-03-28  
这个是我自己封装的方法,当然找不到了
那怎么办。。
21 楼 sjxinrui 2012-03-28  
我肿么看不懂啊。。。
20 楼 sarin 2011-11-22  
wolg_001 写道
请问下你用的是dom4j的哪个版本吧的包? 我的getServMgr() 为什么不能找到?

这个是我自己封装的方法,当然找不到了
19 楼 wolg_001 2011-11-22  
请问下你用的是dom4j的哪个版本吧的包? 我的getServMgr() 为什么不能找到?
18 楼 sarin 2011-03-21  
lgb860316 写道
额~~~如果每次数据变化时,都要写变XML文件的话那效率可想而之。
在FusionCharts的帮助文档中有JS、JSP、ASP等多钟实现方式。无需写XML的。来段代码吧。JS实现的。

  function ratingStorageGrah0(a,b,c){
  var sum = a+b+c;
  timely =a/sum*100;
  obsolete =b/sum*100;
  lack =c/sum*100;
  var strXML = "";
strXML +="<chart bgColor='#ffffff' baseFont='宋体' baseFontSize='12' showValues='1' numberSuffix='%'  formatNumberScale='0' showBorder='0'>";
strXML +="<set label='在线' value='"+a+"' />";
strXML +="<set label='离线' value='"+b+"' />";
strXML +="<set label='近线' value='"+c+"' />";
strXML +="</chart>";
var ratingStorageGrah0Div = document.getElementById("ratingStorageGrah0");
var chartX = ratingStorageGrah0Div.style.width;
var chartY = ratingStorageGrah0Div.style.height;
  var chart = new FusionCharts("<%=path%>/js/public/fusioncharts/Charts/Pie3D.swf", "", chartX, chartY, "0", "0");
   chart.setDataXML(strXML)  
     chart.render("ratingStorageGrah0");
    
  }

这个当然是个问题,而本文是主要来说明DOM4J的使用的
17 楼 lgb860316 2011-03-21  
额~~~如果每次数据变化时,都要写变XML文件的话那效率可想而之。
在FusionCharts的帮助文档中有JS、JSP、ASP等多钟实现方式。无需写XML的。来段代码吧。JS实现的。

  function ratingStorageGrah0(a,b,c){
  var sum = a+b+c;
  timely =a/sum*100;
  obsolete =b/sum*100;
  lack =c/sum*100;
  var strXML = "";
strXML +="<chart bgColor='#ffffff' baseFont='宋体' baseFontSize='12' showValues='1' numberSuffix='%'  formatNumberScale='0' showBorder='0'>";
strXML +="<set label='在线' value='"+a+"' />";
strXML +="<set label='离线' value='"+b+"' />";
strXML +="<set label='近线' value='"+c+"' />";
strXML +="</chart>";
var ratingStorageGrah0Div = document.getElementById("ratingStorageGrah0");
var chartX = ratingStorageGrah0Div.style.width;
var chartY = ratingStorageGrah0Div.style.height;
  var chart = new FusionCharts("<%=path%>/js/public/fusioncharts/Charts/Pie3D.swf", "", chartX, chartY, "0", "0");
   chart.setDataXML(strXML)  
     chart.render("ratingStorageGrah0");
    
  }
16 楼 風一樣的男子 2010-08-29  
hellostory 写道
風一樣的男子 写道
sarin 写道
風一樣的男子 写道
sarin 写道
風一樣的男子 写道
曾经写过通用的
查询SQL、统计图配置都配在 XML 中
一个节点对应一个统计

不明白,和这个有关系么?


难道你的系统很多统计图表
每个统计图表都写个对应的 ChartAction 吗?

那肯定不能了,演示就很简单了。实际应用应该使用工厂模式或者写一个助手类实现。


写个帮助类读XML
把图表信息、统计SQL配置到XML文件中
这样子就一个 action、一个jsp
通过不同的参数读取 xml 文件中的不同节点完成一个图表生成
要添加也方便,在XML文件加节点就是了

这样还是不方便,因为很多时候数据是放在数据库,而且dataSet的数量是不固定的,不管怎样,似乎现在都还没看到很好的封装方法

废话,谁的数据不在数据库里?
不想说太多
<!-- XXXX 按部门 -->
	<spvs name="XXXX">
		<chart palette='1' caption='XXXX统计分析' yAxisName='业务量' rotateYAxisName='0' yAxisNameWidth='25' chartRightMargin='28'
			 showvalues='1' decimals='0' formatNumberScale='0' formatNumber='0' useRoundEdges='1' legendBorderAlpha='0' 
			baseFont="宋体" baseFontSize="14" outCnvBaseFont='宋体' link="/chart/multiSeriesItemChart.action?chartName=superviseItem" />
		<datasets>
			<dataset seriesName="红牌" color="FF0000" showValues="1">
				b
			</dataset>
			<dataset seriesName="黄牌" color="F6BD0F" showValues="1">
				c
			</dataset>
			<dataset seriesName="预警" color="AFD8F8" showValues="1">
				d
			</dataset>
			<dataset seriesName="正常" color="C7EDCC" showValues="1">
				e
			</dataset>
		</datasets>
		<chartTypes>
			<!-- 如果为空或无子项,取全局配置 -->
		</chartTypes>
		<sql>
			<![CDATA[
			SELECT DEP.DEPART_ABBR_NAME A, DEP.Depart_Id,
			SUM(DECODE(T.ACTIVE_STATUS, 9, 1, 0)) B,
			SUM(DECODE(T.ACTIVE_STATUS, 5, 1, 0)) C,
			SUM(DECODE(T.ACTIVE_STATUS, 1, 1, 0)) D,
			SUM(DECODE(T.ACTIVE_STATUS, 0, 1, 0)) E FROM
			DEPARTMENT DEP, S_INDEX T WHERE DEP.DEPART_ID =
			T.DEPART_ID(+) ${defCon} GROUP BY DEP.DEPART_ABBR_NAME, DEP.Depart_Id
			]]>
		</sql>
	</spvs>
15 楼 hellostory 2010-08-24  
風一樣的男子 写道
sarin 写道
風一樣的男子 写道
sarin 写道
風一樣的男子 写道
曾经写过通用的
查询SQL、统计图配置都配在 XML 中
一个节点对应一个统计

不明白,和这个有关系么?


难道你的系统很多统计图表
每个统计图表都写个对应的 ChartAction 吗?

那肯定不能了,演示就很简单了。实际应用应该使用工厂模式或者写一个助手类实现。


写个帮助类读XML
把图表信息、统计SQL配置到XML文件中
这样子就一个 action、一个jsp
通过不同的参数读取 xml 文件中的不同节点完成一个图表生成
要添加也方便,在XML文件加节点就是了

这样还是不方便,因为很多时候数据是放在数据库,而且dataSet的数量是不固定的,不管怎样,似乎现在都还没看到很好的封装方法
14 楼 風一樣的男子 2010-07-14  
sarin 写道
風一樣的男子 写道
sarin 写道
風一樣的男子 写道
曾经写过通用的
查询SQL、统计图配置都配在 XML 中
一个节点对应一个统计

不明白,和这个有关系么?


难道你的系统很多统计图表
每个统计图表都写个对应的 ChartAction 吗?

那肯定不能了,演示就很简单了。实际应用应该使用工厂模式或者写一个助手类实现。


写个帮助类读XML
把图表信息、统计SQL配置到XML文件中
这样子就一个 action、一个jsp
通过不同的参数读取 xml 文件中的不同节点完成一个图表生成
要添加也方便,在XML文件加节点就是了
13 楼 sarin 2010-07-14  
風一樣的男子 写道
sarin 写道
風一樣的男子 写道
曾经写过通用的
查询SQL、统计图配置都配在 XML 中
一个节点对应一个统计

不明白,和这个有关系么?


难道你的系统很多统计图表
每个统计图表都写个对应的 ChartAction 吗?

那肯定不能了,演示就很简单了。实际应用应该使用工厂模式或者写一个助手类实现。
12 楼 風一樣的男子 2010-07-14  
sarin 写道
風一樣的男子 写道
曾经写过通用的
查询SQL、统计图配置都配在 XML 中
一个节点对应一个统计

不明白,和这个有关系么?


难道你的系统很多统计图表
每个统计图表都写个对应的 ChartAction 吗?
11 楼 left819 2010-07-14  
不错的东东
10 楼 maodiesky 2010-07-14  
以前帮公司搞过,所有的属性配置完全写了自己的一套界面,可以按照用户要求快速自定义图形属性,数据的获取有统一的接口

相关推荐

Global site tag (gtag.js) - Google Analytics