-
最近在公司做了一个数据的报表统计,主要实现了数据的饼状图、柱状图、折线图展示,写了这篇博客和大家分享一下:
学习参考资料在我的博客里面:http://download.csdn.net/detail/harderxin/6804365,里面有学习jfreechart相关的jar文件和学习文档,大家可以下载下来进行查看,我这里下载的jfreechart版本是1.0.17,对于现在来说,应该算是最新版本了吧!
一、环境配置:
1、导入struts相关jar包,我这里使用的是struts2
2、导入struts与jfreechart结合的jar包,struts2-jfreechart-plugin-2.3.1.jar,这个jar包在struts里面可能就已经存在了,这是struts2在这方面最好了处理,因为我们的jfreechart就是针对于java语言做报表工作的,很强大哦!
3、导入jfreechart核心包,解压我的文件,在jfreechart/lib/目录下,jcommon-1.0.21.jar、jfreechart-1.0.17.jar
4、关于struts2的部署和配置在这里就不像大家描述了,大家可以在网上找相关资料进行学习,我这个项目中运用到了struts2和spring框架,要用到jfreechart,我们在设置struts中的package配置时应该继承jfreechart-default,而不是像以前那样继承struts-default,理由应该是我们要在struts2中使用jfreechart,就会用到struts2-jfreechart-pluginjar包,所以它里面除了封装自己的逻辑外,也继承了struts-default,所以我们需要继承jfreechart-default:
-
<span style="font-size:18px;"><struts> <package name="query" extends="jfreechart-default" namespace="/"> <result name="show" type="chart"> <param name="width">600 <param name="height">400 </result> </action> </package> </struts></span>
12345678910<struts>
<
package
name=
"query"
extends
=
"jfreechart-default"
namespace=
"/"
>
<result name=
"show"
type=
"chart"
>
<param name=
"width"
>
600
<param name=
"height"
>
400
</result>
</action>
</
package
>
</struts>
我给Action定义为QueryAction,因为我使用了spring,所以class="queryAction",如果大家只用到了struts2,那就得把action的全路径都写在里面了。这里type="chart",表示我们使用的是jfreechart输出,如果我们没有使用struts框架,只是使用基本的Servlet处理用户请求,那么我们需要在web.xml中进行相应的配置:12345678<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>/DisplayChart</url-pattern>
</servlet-mapping>
二、Action处理:
我们编写的Action中需定义一个JFreeChart对象,名称也必须为chart,可能是框架规定的,然后提供其相应的set和get方法:
123456789101112public
class
QueryAction {
private
JFreeChart chart;
public
JFreeChart getChart() {
return
chart;
}
public
void
setChart(JFreeChart chart) {
this
.chart = chart;
}
}
我们在处理逻辑的时候只需要获得相应的JfreeChart对象即可:
12345678910111213141516171819public
String show()
throws
Exception {
String type=request.getParameter(
"type"
);
Map<string,
double
> map=
null
;
if
(type!=
null
&&type.equals(
"area"
)){
map=queryService.findRepairRecByArea();
this
.chart = JfreeChartUtil.createPieChart(
"各地区产品数量统计"
, map);
//饼状图
}
else
if
(type!=
null
&&type.equals(
"person"
)){
List<map<string,object>> list=queryService.findRepairRec(PERSON);
map=
new
HashMap<string,
double
>();
for
(Map<string,object> repairRec:list){
String person=repairRec.get(
"repair_person"
)+
""
;
Double count=Double.parseDouble(repairRec.get(
"count"
)+
""
);
map.put(person, count);
}
this
.chart = JfreeChartUtil.createBarChart(
"各人员维修产品数量统计"
,
"维修人员"
,
"产品数量"
, map);
//柱状图
}
//this.chart = JfreeChartUtil.createLineChart("折线图", "X轴标签", "Y轴标签");
return
"show"
;
}</string,object></string,
double
></map<string,object></string,
double
>
我在逻辑处理的时候,把相应的图的逻辑封装为JfreeChartUtil类,传入相应的参数过去,其中数据的显示则是从后台查询出来的,然后自己封装为一个Map:其中键值为描述标签信息,值为相应的数值,然后在设置的时候循环遍历Map取得其中的键和值。三、jsp页面:
jsp页面中的代码就很简单了,直接一个img标签,然后src中写上访问的action名称即可:
1234<br><br>
<center>
<img style=
"display: none;"
alt=
"jfreechart"
src=
""
><img title=
"图片加载中..."
alt=
"加载中..."
src=
"http://www.2cto.com/statics/images/s_nopic.gif"
>
</center>
我们在访问的时候直接访问这个jsp页面即可:http://localhost:8080/xroa/index.jsp,它会自动请求Action显示相应的报表;
四、逻辑处理,下面,让我们来看看我们的逻辑处理这一大块,说白了就是掌握里面的API,然后灵活调用就可以了,因为代码里面有注解,所以我就不多说了,大家可以看看代码,如果弄不懂,可以看我那个资源文件里面的中文文档,或者自己从网上进行查找,因为里面的类比较多,所以我就不一一把那些类写出来了,大家灵活运用就可以了!
1)创建饼状图:
实现代码:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061/**
* 创建饼状图
* @param title 标题
* @param map 键值对
* @return
*/
public
static
JFreeChart createPieChart(String title,Map<string,
double
> map){
DefaultPieDataset dpd=createPieDataset(map);
// 创建PieChart对象(标题,数据集,是否显示图例,是否生成工具提示,是否生成URL链接)
JFreeChart chart = ChartFactory.createPieChart3D(title, dpd,
true
,
true
,
false
);
setPie3DStyle(chart);
return
chart;
}
/**
* 创建饼状图数据
* @param map
* @return
*/
private
static
DefaultPieDataset createPieDataset(Map<string,
double
> map){
DefaultPieDataset dpd =
new
DefaultPieDataset();
Set<string> set=map.keySet();
for
(Iterator<string> itor=set.iterator();itor.hasNext();){
String key=itor.next();
dpd.setValue(key, map.get(key));
}
return
dpd;
}
/**
* 设置饼状图样式
* @param chart
*/
private
static
void
setPieStyle(JFreeChart chart){
PiePlot plot = (PiePlot) chart.getPlot();
Font font =
new
Font(
"宋体"
, Font.ITALIC,
12
);
chart.getTitle().setFont(
new
Font(
"宋体"
, Font.BOLD,
22
));
//方块距离饼的距离 只要负值就能把数据放到饼里
plot.setLabelFont(font);
//去掉label
//plot.setLabelGenerator(null);
//在label上显示百分比
//plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{2}"));
//如果百分比要显示一位小数
//plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{2}",new DecimalFormat("0.0"),new DecimalFormat("0.0%")));
//在label上显示实际数值
//plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{1}"));
//是否显示线 fasle就不显示了
//plot.setLabelLinkMargin(-0.8);
//plot.setLabelLinksVisible(false);
//有时我们想突出某一个来显示,需要加入下面一句:第一个参数是key,第二个参数是突出显示的大小(可以自己调整一下看看效果就明白了)
//plot.setExplodePercent("城管强拆",0.23);
//设置相应的数据显示效果
//StandardPieSectionLabelGenerator standarPieIG = new StandardPieSectionLabelGenerator("{0}:({1},{2})", new DecimalFormat("0.0"), new DecimalFormat("0.0"));
StandardPieSectionLabelGenerator standarPieIG =
new
StandardPieSectionLabelGenerator(
"{0}:({1},{2})"
,
new
DecimalFormat(
"0.0"
),
new
DecimalFormat(
"0.0%"
));
plot.setLabelGenerator(standarPieIG);
//没有数据的时候所显示的内容
plot.setNoDataMessage(
"没有相应的数据显示"
);
chart.getLegend().setItemFont(font);
}</string></string></string,
double
></string,
double
>
如果我们需要创建3D样式的饼状图,只需要修改其样式即可:123456789101112131415161718192021/**
* 设置饼状图3D样式
* @param chart
*/
private
static
void
setPie3DStyle(JFreeChart chart){
//获得3D的水晶饼图对象
PiePlot3D pieplot3d = (PiePlot3D) chart.getPlot();
//设置开始角度
pieplot3d.setStartAngle(150D);
//设置方向为”顺时针方向“
pieplot3d.setDirection(Rotation.CLOCKWISE);
//设置透明度,0.5F为半透明,1为不透明,0为全透明
pieplot3d.setForegroundAlpha(
0
.5F);
pieplot3d.setNoDataMessage(
"没有相应的数据显示"
);
Font font =
new
Font(
"宋体"
, Font.ITALIC,
12
);
chart.getTitle().setFont(
new
Font(
"宋体"
, Font.BOLD,
22
));
pieplot3d.setLabelFont(font);
chart.getLegend().setItemFont(font);
StandardPieSectionLabelGenerator standarPieIG =
new
StandardPieSectionLabelGenerator(
"{0}:({1},{2})"
,
new
DecimalFormat(
"0.0"
),
new
DecimalFormat(
"0.0%"
));
pieplot3d.setLabelGenerator(standarPieIG);
}
2)创建柱状图(显示内容为单个数据):1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162/**
* 创建柱状图
* @param title 标题
* @param XLabel X轴标签
* @param YLabel Y轴标签
* @param map 键值对
* @return
*/
public
static
JFreeChart createBarChart(String title,String XLabel,String YLabel,Map<string,
double
> map){
DefaultCategoryDataset dataset=createBarDataSet(map);
//创建一个柱状图(图表标题,X轴显示标签,Y轴显示标签,数据集,图表方向(水平or垂直),是否显示图例[对于简单图应为false],是否生成工具,是否生成url链接)
JFreeChart chart = ChartFactory.createBarChart3D(title,XLabel, YLabel, dataset, PlotOrientation.VERTICAL,
false
,
false
,
false
);
setBarStyle(chart);
return
chart;
}
/**
* 创建柱状图数据
* @param list
* @return
*/
private
static
DefaultCategoryDataset createBarDataSet(Map<string,
double
> map){
DefaultCategoryDataset dataset =
new
DefaultCategoryDataset();
Set<string> set=map.keySet();
for
(Iterator<string> itor=set.iterator();itor.hasNext();){
String key=itor.next();
dataset.addValue(map.get(key),
""
, key);
}
return
dataset;
}
/**
* 设置柱状图样式
* @param chart
*/
private
static
void
setBarStyle(JFreeChart chart){
CategoryPlot plot=chart.getCategoryPlot();
//设置标题字体样式
chart.getTitle().setFont(
new
Font(
"黑体"
, Font.ITALIC,
22
));
//取得横轴和设置横轴样式
CategoryAxis categoryAxis = plot.getDomainAxis();
categoryAxis.setLabelFont(
new
Font(
"宋体"
, Font.BOLD,
22
));
//横轴分类标签
categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.STANDARD);
categoryAxis.setTickLabelFont(
new
Font(
"宋体"
, Font.BOLD,
22
));
//取得纵轴和设置纵轴样式
NumberAxis numberAxis = (NumberAxis) plot.getRangeAxis();
numberAxis.setLabelFont(
new
Font(
"宋体"
, Font.BOLD,
22
));
//显示每个柱的数值,并修改该数值的字体属性
BarRenderer3D renderer =
new
BarRenderer3D();
renderer.setBaseItemLabelGenerator(
new
StandardCategoryItemLabelGenerator());
renderer.setBaseItemLabelsVisible(
true
);
//默认的数字显示在柱子中,通过如下两句可调整数字的显示
//注意:此句很关键,若无此句,那数字的显示会被覆盖,给人数字没有显示出来的问题 ,将数字显示在柱状图上面
renderer.setBasePositiveItemLabelPosition(
new
ItemLabelPosition(
ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_LEFT));
renderer.setItemLabelAnchorOffset(10D);
//设置每个地区所包含的平行柱的之间距离
//renderer.setItemMargin(0.3);
plot.setRenderer(renderer);
}</string></string></string,
double
></string,
double
>
创建带有多个数据的柱状图:不同的地方主要是数据提供不一样:在dataset.addValue()中第二个参数部位""或null就行了,我们也可以使用数组的方式提供:
1234567891011/**
* 创建柱状图数据的第二种方式
* @return
*/
private
static
CategoryDataset createBarDataSet2(){
double
[][] data =
new
double
[][] {{
1310
,
1220
,
1110
,
1000
},{
720
,
700
,
680
,
640
},{
1130
,
1020
,
980
,
800
},{
440
,
400
,
360
,
300
}};
String[] rowKeys = {
"pig"
,
"beef"
,
"chicken"
,
"fish"
};
String[] columnKeys = {
"Guangzhou"
,
"Shenzhen"
,
"Dongguan"
,
"Foshan"
};
CategoryDataset dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data);
return
dataset;
}
3)创建折线图:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869/**
* 创建折线图
* @param title
* @param XLabel
* @param YLabel
* @return
*/
public
static
JFreeChart createLineChart(String title,String XLabel,String YLabel) {
//该数据的Demo由系统提供,故不传入相应的Map或List数据了
DefaultCategoryDataset dataset=createLineDataset();
// 定义图表对象(折线图名称,横坐标名称,纵坐标名称,数据, 水平显示图像)
JFreeChart chart = ChartFactory.createLineChart(title,XLabel,YLabel,dataset,PlotOrientation.VERTICAL,
true
,
true
,
false
);
setLineStyle(chart);
return
chart;
}
/**
* 生成折线图数据
* @return
*/
private
static
DefaultCategoryDataset createLineDataset() {
DefaultCategoryDataset linedataset =
new
DefaultCategoryDataset();
// 各曲线名称
String series1 =
"冰箱"
;
String series2 =
"彩电"
;
String series3 =
"洗衣机"
;
// 横轴名称(列名称)
String type1 =
"1月"
;
String type2 =
"2月"
;
String type3 =
"3月"
;
linedataset.addValue(
0.0
, series1, type1);
linedataset.addValue(
4.2
, series1, type2);
linedataset.addValue(
3.9
, series1, type3);
linedataset.addValue(
1.0
, series2, type1);
linedataset.addValue(
5.2
, series2, type2);
linedataset.addValue(
7.9
, series2, type3);
linedataset.addValue(
2.0
, series3, type1);
linedataset.addValue(
9.2
, series3, type2);
linedataset.addValue(
8.9
, series3, type3);
return
linedataset;
}
/**
* 设置折线图样式
*
* @param chart
*/
private
static
void
setLineStyle(JFreeChart chart){
CategoryPlot plot = chart.getCategoryPlot();
//设置标题字体样式
chart.getTitle().setFont(
new
Font(
"黑体"
, Font.ITALIC,
22
));
//取得横轴和设置横轴样式
CategoryAxis categoryAxis = plot.getDomainAxis();
categoryAxis.setLabelFont(
new
Font(
"宋体"
, Font.BOLD,
22
));
//横轴分类标签
categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.STANDARD);
categoryAxis.setTickLabelFont(
new
Font(
"宋体"
, Font.BOLD,
22
));
plot.setRangeGridlinesVisible(
true
);
//是否显示格子线
plot.setBackgroundAlpha(
0
.3f);
//设置背景透明度
NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
rangeAxis.setLabelFont(
new
Font(
"宋体"
, Font.BOLD,
22
));
//设置工具工具提示字体样式
chart.getLegend().setItemFont(
new
Font(
"宋体"
, Font.BOLD,
22
));
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setAutoRangeIncludesZero(
true
);
rangeAxis.setUpperMargin(
0.20
);
rangeAxis.setLabelAngle(Math.PI /
2.0
);
}
好了,在这里基本上就完成了,不过需要注意以下几点:1)有人说使用中文会出现乱码现象,我想主要是没有设置相应的字体样式,我这里面都对其进行了设置,所以就不会出现乱码现象了;
2)除了柱状图、折线图、饼状图,还有其他的图,例如分布图、区域图、混合图等等,都可以通过里面提供的API进行创建,大家可以再网上查找相关的资料进行学习即可,学会举一反三;
3)我们如果不输出到页面,也可以使用文件的方式保存,里面有一个util类可以帮我们进行处理,获得相应的FileOutStream,传入到参数中
* 调用下面方法可以输出到相应的FileOutputStream
* ChartUtilities.writeChartAsJPEG(out, quality, chart, width, height, info);其中out为输出流对象,quality为输出图片的质量,chart为相应的JFreechart对象,宽度、高度、信息
当我们使用Servlet进行处理的时候,out可以使用response.getOutputStream获得;
4)还有很多的API在这里没有用到,里面其实还有很强大的功能,大家自己根据自己的项目需求去学习吧,这里只是一个指引而已哦,欢迎一起交流分享!!
Struts2结合Jfreechart实现数据报表统计
最新推荐文章于 2019-05-13 13:27:00 发布