V2.0的项目开始,卸下组长的责任投入了一个个小模块的技术研究里,一直以来技术研究好像是我的弱点,可能是因为平时积累不够的原因,但是这次顶着压力接下了这个任务,还是努力的去做了,尽管最终的结果可能不是很漂亮,但是至少还是迈出了一步。
废话少说,先说说我的需求:因为ITOO的系统中多个子系统都涉及到图表的使用,所以需要封装一个公共的方法来供各子系统调用,这次迭代主要完成的图表有:柱形图,折线图,饼形图;下面从底层封装开始写写我封装jfreechart图表的过程,并说一下它的不足,希望得到更多的指教。
第一步:
由于项目是用maven管理的,所以需要在itoo-tool的pom文件中引入jreechart要用到的jar包:
<!-- 图表引入jar包********陈丽娜*********start****2015-1-29****-->
<dependency>
<groupId>jfreechart</groupId>
<artifactId>jfreechart</artifactId>
<version>${jfreechart.version}</version>
</dependency>
<!-- 图表引入jar包********陈丽娜*********end****2015-1-29**** -->
第二步:
引入jar包之后就可以使用jfreechart相关的类与属性,这时候就可以封装图表工具类了,如下为工具类中的代码:
package com.tgb.itoo.tool.jfreechart;
import java.awt.Font;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.security.KeyStore.Entry;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.xml.messaging.ReqRespListener;
import org.jfree.chart.ChartColor;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.servlet.ServletUtilities;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
/**
* 图表工具类封装
* @author 陈丽娜
* @version 1.0.0 , 2015年1月29日 下午3:28:54
*/
public class JfreeChartUntil {
private JFreeChart chart;
/**
* 柱状图公共方法
* @param title 柱状图标题
* @param xTitle 柱状图x轴
* @param yTitle 柱状图y轴
* @param map 需要生成图表的数据
* @param request 访问数据
* @return 返回一个图片地址
* @throws IOException 抛出异常
*/
public String getColumnChart(String title,String xTitle,String yTitle,Map<String , Integer> map,HttpServletRequest request) throws IOException{
DefaultCategoryDataset dataset=new DefaultCategoryDataset();
//取出横坐标要统计的数据,遍历传递过来的map数据
for (Map.Entry<String , Integer> entry : map.entrySet()) {
//System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
dataset.addValue(entry.getValue(), "", entry.getKey());
}
//CategoryDataset dataset=getDataset2();
//创建一个柱形图
chart=ChartFactory.createBarChart3D(title, xTitle, yTitle, dataset, PlotOrientation.VERTICAL, false, false, false);
CategoryPlot categoryPlot=chart.getCategoryPlot();
BarRenderer barRenderer=(BarRenderer)categoryPlot.getRenderer();
categoryPlot.setRangeGridlinePaint(ChartColor.DARK_BLUE);
barRenderer.setMaximumBarWidth(0.06); //定义柱形的宽度
//保存生成的图表为图片
String fileName=ServletUtilities.saveChartAsJPEG(chart, 700, 600, request.getSession());
//获取图片的路径
String chartURL=request.getContextPath()+"/chart?filename=" +fileName;
//返回图片路径
return chartURL;
}
/**
* 生成饼形图
* @param title 饼形图标题
* @param map 需要统计为饼形图的数据
* @param request 访问
* @return 返回jfreechart生成的图片地址
* @throws IOException 抛出异常
*/
public String getPieChart(String title,Map<String , Integer> map,HttpServletRequest request) throws IOException{
DefaultPieDataset dataset=new DefaultPieDataset();
//取出横坐标要统计的数据,遍历传递过来的map数据
for (Map.Entry<String , Integer> entry : map.entrySet()) {
dataset.setValue(entry.getKey(),entry.getValue());
}
chart=ChartFactory.createPieChart(title, dataset, false, false, false);
//获取饼形图对象
PiePlot piePlot=(PiePlot)chart.getPlot();
//饼形图显示百分比
//{0}表示选项,{1}表示数值,{2}表示百分比
StandardPieSectionLabelGenerator standarPieIG=new StandardPieSectionLabelGenerator(
"{0}:({1},{2})", NumberFormat.getNumberInstance(), NumberFormat.getPercentInstance());
//为饼形图设置对应的显示百分比格式
piePlot.setLabelGenerator(standarPieIG);
//调用修改格式方法
//changeStyle(chart);
//保存生成的图表为图片
String fileName=ServletUtilities.saveChartAsJPEG(chart, 700, 600, request.getSession());
//获取图片的路径
String chartURL=request.getContextPath()+"/chart?filename=" +fileName;
//返回图片路径
return chartURL;
}
public String getLineChart(String title,String xTitle,String yTtitel,Map<String , Integer> map,HttpServletRequest request) throws IOException{
DefaultCategoryDataset dataset=new DefaultCategoryDataset();
//取出横坐标要统计的数据,遍历传递过来的map数据
for (Map.Entry<String , Integer> entry : map.entrySet()) {
dataset.addValue(entry.getValue(), "", entry.getKey());
}
chart=ChartFactory.createLineChart(title, xTitle, yTtitel, dataset, PlotOrientation.VERTICAL, false, false, false);
//调用修改格式方法
//changeStyle(chart);
//保存生成的图表为图片
String fileName=ServletUtilities.saveChartAsJPEG(chart, 700, 600, request.getSession());
//获取图片的路径
String chartURL=request.getContextPath()+"/chart?filename=" +fileName;
//返回图片路径
return chartURL;
}
}
其实大家也可以看出封装起来并不困难,但是就是这样的封装可以使每个想要使用图表的功能只需要传递标题和统计数据。
第三步:使用图表功能的模块需要在自己的web层中的web.xml中配置图片存放路径:
Web.xml:
<!-- jfeechart配置*****2015-2-1****陈丽娜******start**** *************************-->
<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>/chart</url-pattern>
</servlet-mapping>
<!-- jfeechart配置*****2015-2-1****陈丽娜******end**** *************************-->
第四步:
在使用图表功能的模块中的controller中写如下的代码:
@RequestMapping("/testJfreechart")
private void testJfreeChart(String jfreechart, HttpServletRequest request,HttpServletResponse response) throws Exception{
//查询建筑工程学院下的所有课程
String id="A6MNqDUqiXar2tmragammb";
List<CourseInfo> listCourseInfo=courseBean.queryAllCourseInfos(id);
Map<String, Integer> map=new HashMap<String, Integer>();
//将查询出的list集合放到map中并统计数据
for(CourseInfo courseInfo : listCourseInfo){
if(courseInfo==null){
continue;
}
//获取课程类型相同的课程数
Integer count=map.get(courseInfo.getCourseType().getCourseTypeName());
if(count!=null){
map.put(courseInfo.getCourseType().getCourseTypeName(), count+1);
}else{
map.put(courseInfo.getCourseType().getCourseTypeName(), 1);
}
}
JfreeChartUntil jfreeChartUntil=new JfreeChartUntil();
jacksonJsonUntil=new JacksonJsonUntil();
String chartUrl="";
//chartUrl=jfreeChartUntil.getColumnChart("课程信息测试柱状图", "课程类型信息","课程数据", map,request);
//判断冲前台传递回来的jfreechart是什么类型
//如果为line则调用折线,如果是pie则调用饼形,如果是column则调用柱形
switch (jfreechart) {
case "line":
chartUrl=jfreeChartUntil.getLineChart("课程信息测试折线图", "课程类型信息", "课程数据", map, request);
break;
case "pie":
chartUrl=jfreeChartUntil.getPieChart("课程信息测试饼形图", map, request);
break;
case "column":
chartUrl=jfreeChartUntil.getColumnChart("课程信息测试柱形图图", "课程类型信息", "课程数据", map, request);
break;
default:
break;
}
//将生成的图表图片路径转成json并返回
jacksonJsonUntil.beanToJson(response, chartUrl);
}
第五步:
前台显示页面
<!--图表demo 弹出框***************陈丽娜***********start********2015-2-6**** -->
<div id="addone" class="easyui-dialog" style="width:700px;height:600px;padding:10px 20px"
title="图表demo" closed="true" buttons="#dlg-buttons" >
<div id="sp"class="easyui-panel" style="padding:5px;">
<input type="radio" name="lang" value="column"><span>柱形图</span>
<input type="radio" name="lang" value="pie"><span>饼形图</span>
<input type="radio" name="lang" value="line"><span>折线图</span><br/>
</div>
<img id="test1"src="" width=100% height=500 >
</div>
<!--图表demo 弹出框***************陈丽娜***********end**********2015-2-6**** -->
$(function(){
$('#sp input').click(function(){
var chart = $(this).val();
// alert(chart);
$("#test1").attr("src","");
$.ajax({
//访问图表的controller
url:'testJfreechart?jfreechart='+chart,
//type:'post',
success:function(data)
{
//alert(data);
$("#test1").attr("src",data);
},
error:function(data){
alert( "图形分析失败,请联系管理员!");
}
});
});
});
大概是这样的,显示效果大概如下:
但是这样的图表有些不美观,没有向highcharts或者Echarts那么的有动感,所以觉得还是封装成Hightcharts或者是Echarts的图表比较高端,正在努力中。