Struts2结合Jfreechart实现数据报表统计

 
 

    最近在公司做了一个数据的报表统计,主要实现了数据的饼状图、柱状图、折线图展示,写了这篇博客和大家分享一下:

学习参考资料在我的博客里面: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>


 

?
1
2
3
4
5
6
7
8
9
10
<struts>
   <packagename="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中进行相应的配置:

?
1
2
3
4
5
6
7
8
<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方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
publicclass QueryAction {
   
   private JFreeChart chart;
   
   public JFreeChart getChart() {
       return chart;
   }
   public voidsetChart(JFreeChart chart) {
       this.chart = chart;
   }
}

我们在处理逻辑的时候只需要获得相应的JfreeChart对象即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
publicString show() throwsException {
   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名称即可:

?
1
2
3
4
<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)创建饼状图:

\

实现代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
* 创建饼状图
* @param title 标题
* @param map 键值对
* @return
*/
publicstatic 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
*/
privatestatic DefaultPieDataset createPieDataset(Map<string,double> map){
   DefaultPieDataset dpd = newDefaultPieDataset();
   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
*/
privatestatic void setPieStyle(JFreeChart chart){
   PiePlot plot = (PiePlot) chart.getPlot();
   Font font = newFont("宋体", Font.ITALIC,12);
   chart.getTitle().setFont(newFont("宋体", 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样式的饼状图,只需要修改其样式即可:

\

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 设置饼状图3D样式
* @param chart
*/
privatestatic 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 = newFont("宋体", Font.ITALIC,12);
   chart.getTitle().setFont(newFont("宋体", 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)创建柱状图(显示内容为单个数据):

\

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* 创建柱状图
* @param title 标题
* @param XLabel X轴标签
* @param YLabel Y轴标签
* @param map 键值对
* @return
*/
publicstatic 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
*/
privatestatic DefaultCategoryDataset createBarDataSet(Map<string,double> map){
   DefaultCategoryDataset dataset = newDefaultCategoryDataset();
   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
*/
privatestatic void setBarStyle(JFreeChart chart){
   CategoryPlot plot=chart.getCategoryPlot();
   //设置标题字体样式
   chart.getTitle().setFont(newFont("黑体", Font.ITALIC,22));
   //取得横轴和设置横轴样式
   CategoryAxis categoryAxis = plot.getDomainAxis();
   categoryAxis.setLabelFont(newFont("宋体", Font.BOLD,22));
   //横轴分类标签
   categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.STANDARD);
   categoryAxis.setTickLabelFont(newFont("宋体", Font.BOLD,22));
   //取得纵轴和设置纵轴样式
   NumberAxis numberAxis = (NumberAxis) plot.getRangeAxis();
   numberAxis.setLabelFont(newFont("宋体", Font.BOLD,22));
   
   //显示每个柱的数值,并修改该数值的字体属性  
   BarRenderer3D renderer = newBarRenderer3D();   
   renderer.setBaseItemLabelGenerator(newStandardCategoryItemLabelGenerator()); 
   renderer.setBaseItemLabelsVisible(true); 
   //默认的数字显示在柱子中,通过如下两句可调整数字的显示  
   //注意:此句很关键,若无此句,那数字的显示会被覆盖,给人数字没有显示出来的问题 ,将数字显示在柱状图上面
   renderer.setBasePositiveItemLabelPosition(newItemLabelPosition( 
           ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_LEFT)); 
   renderer.setItemLabelAnchorOffset(10D); 
    //设置每个地区所包含的平行柱的之间距离  
    //renderer.setItemMargin(0.3);  
   plot.setRenderer(renderer); 
}</string></string></string,double></string,double>


创建带有多个数据的柱状图:

\

不同的地方主要是数据提供不一样:在dataset.addValue()中第二个参数部位""或null就行了,我们也可以使用数组的方式提供:

?
1
2
3
4
5
6
7
8
9
10
11
/**
* 创建柱状图数据的第二种方式
* @return
*/
privatestatic 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)创建折线图:

\

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* 创建折线图
* @param title
* @param XLabel
* @param YLabel
* @return
*/
publicstatic 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
*/
privatestatic DefaultCategoryDataset createLineDataset() {
   DefaultCategoryDataset linedataset = newDefaultCategoryDataset();
   // 各曲线名称
   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
*/
privatestatic void setLineStyle(JFreeChart chart){
   CategoryPlot plot = chart.getCategoryPlot();
   //设置标题字体样式
   chart.getTitle().setFont(newFont("黑体", Font.ITALIC,22));
   //取得横轴和设置横轴样式
   CategoryAxis categoryAxis = plot.getDomainAxis();
   categoryAxis.setLabelFont(newFont("宋体", Font.BOLD,22));
   //横轴分类标签
   categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.STANDARD);
   categoryAxis.setTickLabelFont(newFont("宋体", Font.BOLD,22));
   plot.setRangeGridlinesVisible(true);//是否显示格子线
   plot.setBackgroundAlpha(0.3f);//设置背景透明度
   NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
   rangeAxis.setLabelFont(newFont("宋体", Font.BOLD,22));
   //设置工具工具提示字体样式
   chart.getLegend().setItemFont(newFont("宋体", 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在这里没有用到,里面其实还有很强大的功能,大家自己根据自己的项目需求去学习吧,这里只是一个指引而已哦,欢迎一起交流分享!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值