在Struts2中,用JFreeChart实现柱状图统计
前段时间学习了一下JFreeChart,现在来整理一下自己所作的实例。
下面分别用两种方式来实现: 一种是以java应用程序的方式,一种是以web项目程序的方式
需要加入的jar包有: jcommon-1.0.17.jar 、 jfreechart-1.0.14.jar(前两个是JFreeChart中所带的,在下载的JFreeChart的lib目录下) 、 struts2-jfreechart-plugin-2.3.16.3.jar(这个是Struts2所带的,在下载的Struts2的lib目录下)、struts2所常用的9个核心jar包 。 jar包的版本可以有所不同
上述jar包放入到项目的WebRoot/WEB-INF/lib目录下
1、 以java应用程序的方式运行,在web项目中的src目录下新建包: com.jfreechart.test , 在该包中新建类 BarChartTest.java
BarChartTest.java
package com.jfreechart.test;
import java.awt.Color;
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.TextAnchor;
public class BarChartTest {
public static void main(String[] args) throws IOException{
//步骤1:创建CategoryDataset对象(准备数据)
CategoryDataset dataset = createDataset();
//步骤2:根据Dataset 生成JFreeChart对象,以及做相应的设置
JFreeChart jfreeChart = createChart(dataset);
//步骤3:将JFreeChart对象输出到文件
saveAsFile("F:\\BarChart.jpg", jfreeChart, 800, 600);
}
/**
* 创建一个dataset,该dataset包含图表要显示的数据
* @return CategoryDataset
*/
public static CategoryDataset createDataset() {
// 图例名称
String[] line = { "文学类", "科技类", "财经类", "娱乐类"};
// 类别
String[] category = { "2008年", "2009年", "2010年", "2012年", "2013年" };
Random random = new Random(); // 实例化Random对象
// 实例化DefaultCategoryDataset对象
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
// 使用循环向数据集合中添加数据
for (int i = 0; i < line.length; i++) {
for (int j = 0; j < category.length; j++) {
dataset.addValue(100000 + random.nextInt(100000), line[i],
category[j]);
}
}
return dataset;
}
/**
* 根据PieDataset创建JFreeChart对象
* @return JFreeChart
*/
public static JFreeChart createChart(CategoryDataset categoryDataset) {
//JFreeChart类是一个制图对象类,先用它来创建一个制图对象chart
//ChartFactory类是制图工厂类,用它来为制图对象chart完成实例化
//createBarChart()是制图工厂的一个方法,用来创建一个常规的柱状图对象
JFreeChart chart = ChartFactory.createBarChart(
"图书销量统计图", //图表标题
"年份", //X轴标题
"销售数量(本)", //Y轴标题
categoryDataset, //数据集
PlotOrientation.HORIZONTAL, //绘制方向
true, //是否显示图例
false, //是否采用标准生成器
false //是否支持超链接
);
//通过JFreeChart对象的 setTitle方法,修改统计图表的标题部分(包括修改图表标题内容、字体大小等)
chart.setTitle(new TextTitle("图书销量统计图", new Font("黑体", Font.ITALIC , 22)));
//调用 JFreeChart对象的 getLegend(int index)方法,取得该图表的指定索引的图例对象,通过 LegendTitle对象来修改统计图表的图例
LegendTitle legend = chart.getLegend(0);
//设置图例的字体和字体大小,即位于下方的字的字体和大小
legend.setItemFont(new Font("宋体", Font.BOLD, 14));
// 设置画布背景色
chart.setBackgroundPaint(new Color(204, 204, 204));
//取得折线图的绘图(plot)对象
CategoryPlot plot = chart.getCategoryPlot();
//设置数据区的背景透明度,范围在0.0~1.0间
plot.setBackgroundAlpha(0.5f);
// 设置数据区的前景透明度,范围在0.0~1.0间
plot.setForegroundAlpha(0.7f);
// 设置横轴字体
plot.getDomainAxis().setLabelFont(new Font("黑体", Font.BOLD, 14));
// 设置坐标轴标尺值字体
plot.getDomainAxis().setTickLabelFont(new Font("宋体", Font.BOLD, 12));
// 设置纵轴字体
plot.getRangeAxis().setLabelFont(new Font("黑体", Font.BOLD, 14));
// 设置绘图区背景色
plot.setBackgroundPaint(Color.WHITE);
// 设置水平方向背景线颜色
plot.setRangeGridlinePaint(Color.BLACK);
// 设置是否显示水平方向背景线,默认值为true
plot.setRangeGridlinesVisible(true);
// 设置垂直方向背景线颜色
plot.setDomainGridlinePaint(Color.BLACK);
// 设置是否显示垂直方向背景线,默认值为false
plot.setDomainGridlinesVisible(false);
// 横轴上的label斜显示
plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45);
// 没有数据时显示的消息
plot.setNoDataMessage("没有相关统计数据");
plot.setNoDataMessageFont(new Font("黑体", Font.CENTER_BASELINE, 16));
plot.setNoDataMessagePaint(Color.RED);
//显示每个柱的数值,并修改该数值的字体属性
BarRenderer renderer = new BarRenderer();
renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
renderer.setBaseItemLabelsVisible(true);
//设置外廓线不可见
renderer.setDrawBarOutline(false);
//设置每个地区所包含的平行柱的之间距离
renderer.setItemMargin(0.2);
//去掉柱子的倒影
renderer.setShadowVisible(false);
//默认的数字显示在柱子中,通过如下两句可调整数字的显示
//注意:此句很关键,若无此句,那数字的显示会被覆盖,给人数字没有显示出来的问题
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE5, TextAnchor.BASELINE_RIGHT));
renderer.setItemLabelAnchorOffset(6D);
//设置每个柱子上的字体
//12号黑体加粗,字体为黑色
renderer.setItemLabelFont(new Font("黑体",Font.BOLD,10));
renderer.setItemLabelPaint(Color.black);
//改变图表中每个系列直方图的填充颜色
renderer.setSeriesPaint(0, new Color(153, 0, 102));
renderer.setSeriesPaint(1, Color.orange);
renderer.setSeriesPaint(2, Color.RED);
renderer.setSeriesPaint(3, new Color(0, 0, 204));
//提交设计的效果
plot.setRenderer(renderer);
return chart;
}
/**
* 保存图表为文件
*/
public static void saveAsFile(String filePath, JFreeChart jfreeChart,
int weight, int height) throws IOException {
//输出图表到文件,saveCharAsJPEG()方法的参数(File file,JFreeChart chart,int width,int height)
ChartUtilities.saveChartAsJPEG(new File(filePath), jfreeChart, weight, height);
}
}
以java应用程序的方式,运行上面的 BarChartTest.java ,便可以在F盘的根目录下产生了一个名叫BarChart.jpg文件,如下图所示:
如想让柱子竖直绘画,只需把上面的
PlotOrientation.HORIZONTAL
改为 PlotOrientation.VERTICAL 即可,修改后的效果如下:
如果有注意的话,修改之后,柱子上面的数值不见了,这时可以根据上述代码的注释来自行设置,只是数值标签的位置被改变了,改变数值标签的位置参数到合适即可,就是修改上述的这两行代码里的参数到合适即可。
//默认的数字显示在柱子中,通过如下两句可调整数字的显示
//注意:此句很关键,若无此句,那数字的显示会被覆盖,给人数字没有显示出来的问题
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE5, TextAnchor.BASELINE_RIGHT));
renderer.setItemLabelAnchorOffset(6D);
2、 以web项目程序的方式运行
(1)在web项目中的src目录下新建包: com.jfreechart.action , 在该包中新建类 BarChartAction.java
BarChartAction.java
package com.jfreechart.action;
import java.awt.Color;
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Random;
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.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.BarRenderer3D;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.TextAnchor;
import com.jfreechart.commons.FileUtil;
import com.opensymphony.xwork2.ActionContext;
public class BarChartAction {
private JFreeChart chart;
// 必须提供 getChart() 方法,且由该方法返回 JFreeChart 对象
public JFreeChart getChart() throws Exception {
//JFreeChart类是一个制图对象类,先用它来创建一个制图对象chart
//ChartFactory类是制图工厂类,用它来为制图对象chart完成实例化
//createBarChart()是制图工厂的一个方法,用来创建一个常规的柱状图对象
chart = ChartFactory.createBarChart(
"图书销量统计图", //图表标题
"年份", //X轴标题
"销售数量(本)", //Y轴标题
createDataset(), //数据集
PlotOrientation.HORIZONTAL, //绘制方向
true, //是否显示图例
false, //是否采用标准生成器
false //是否支持超链接
);
//通过JFreeChart对象的 setTitle方法,修改统计图表的标题部分(包括修改图表标题内容、字体大小等)
chart.setTitle(new TextTitle("图书销量统计图", new Font("黑体", Font.ITALIC , 22)));
//调用 JFreeChart对象的 getLegend(int index)方法,取得该图表的指定索引的图例对象,通过 LegendTitle对象来修改统计图表的图例
LegendTitle legend = chart.getLegend(0);
//设置图例的字体和字体大小,即位于下方的字的字体和大小
legend.setItemFont(new Font("宋体", Font.BOLD, 14));
// 设置画布背景色
chart.setBackgroundPaint(new Color(204, 204, 204));
//取得折线图的绘图(plot)对象
CategoryPlot plot = chart.getCategoryPlot();
//设置数据区的背景透明度,范围在0.0~1.0间
plot.setBackgroundAlpha(0.5f);
// 设置数据区的前景透明度,范围在0.0~1.0间
plot.setForegroundAlpha(0.7f);
// 设置横轴字体
plot.getDomainAxis().setLabelFont(new Font("黑体", Font.BOLD, 14));
// 设置坐标轴标尺值字体
plot.getDomainAxis().setTickLabelFont(new Font("宋体", Font.BOLD, 12));
// 设置纵轴字体
plot.getRangeAxis().setLabelFont(new Font("黑体", Font.BOLD, 14));
// 设置绘图区背景色
plot.setBackgroundPaint(Color.WHITE);
// 设置水平方向背景线颜色
plot.setRangeGridlinePaint(Color.BLACK);
// 设置是否显示水平方向背景线,默认值为true
plot.setRangeGridlinesVisible(true);
// 设置垂直方向背景线颜色
plot.setDomainGridlinePaint(Color.BLACK);
// 设置是否显示垂直方向背景线,默认值为false
plot.setDomainGridlinesVisible(false);
// 横轴上的label斜显示
plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45);
// 没有数据时显示的消息
plot.setNoDataMessage("没有相关统计数据");
plot.setNoDataMessageFont(new Font("黑体", Font.CENTER_BASELINE, 16));
plot.setNoDataMessagePaint(Color.RED);
//显示每个柱的数值,并修改该数值的字体属性
BarRenderer renderer = new BarRenderer();
renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
renderer.setBaseItemLabelsVisible(true);
//设置外廓线不可见
renderer.setDrawBarOutline(false);
//设置每个地区所包含的平行柱的之间距离
renderer.setItemMargin(0.2);
//去掉柱子的倒影
renderer.setShadowVisible(false);
//默认的数字显示在柱子中,通过如下两句可调整数字的显示
//注意:此句很关键,若无此句,那数字的显示会被覆盖,给人数字没有显示出来的问题
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE5, TextAnchor.BASELINE_RIGHT));
renderer.setItemLabelAnchorOffset(6D);
//设置每个柱子上的字体
//12号黑体加粗,字体为黑色
renderer.setItemLabelFont(new Font("黑体",Font.BOLD,10));
renderer.setItemLabelPaint(Color.black);
//改变图表中每个系列直方图的填充颜色
renderer.setSeriesPaint(0, new Color(153, 0, 102));
renderer.setSeriesPaint(1, Color.orange);
renderer.setSeriesPaint(2, Color.RED);
renderer.setSeriesPaint(3, new Color(0, 0, 204));
//提交设计的效果
plot.setRenderer(renderer);
//设置生成的图表的文件名
String fileName = "BarChartBook.jpg";
//设置图表输出的指定路径
String filePath = FileUtil.getWebRootPath()+"images\\chart\\"+fileName;
//输出图表到文件
saveAsFile(filePath, chart, 800, 600);
//取得request对象
Map request = (Map)ActionContext.getContext().get("request");
//把生成的图表文件的路径filePath放进request对象中
request.put("filePath", filePath);
return chart;
}
/**
* 保存图表为文件
*/
public static void saveAsFile(String filePath, JFreeChart jfreeChart,
int weight, int height) throws IOException {
//输出图表到文件,saveCharAsJPEG()方法的参数(File file,JFreeChart chart,int width,int height)
ChartUtilities.saveChartAsJPEG(new File(filePath), jfreeChart, weight, height);
}
/**
* 创建一个dataset,该dataset包含图表要显示的数据
* @return CategoryDataset
*/
public static CategoryDataset createDataset() {
// 图例名称
String[] line = { "文学类", "科技类", "财经类", "娱乐类" };
// 类别
String[] category = { "2008年", "2009年", "2010年", "2012年", "2013年" };
Random random = new Random(); // 实例化Random对象
// 实例化DefaultCategoryDataset对象
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
// 使用循环向数据集合中添加数据
for (int i = 0; i < line.length; i++) {
for (int j = 0; j < category.length; j++) {
dataset.addValue(100000 + random.nextInt(100000), line[i],
category[j]);
}
}
return dataset;
}
//在struts.xml中的对应<action>里,应该写的是 method="barChart" 和 <result type="chart">
public String barChart() {
return "success";
}
}
(2)在web项目中的src目录下新建struts.xml文件
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<!-- 配置 Struts 2 应用中的常量 -->
<constant name="struts.i18n.encoding" value="UTF-8"/>
<!-- 配置本应用中的包,继承 jfreechart-default 包 -->
<package name="chart" extends="jfreechart-default">
<!-- 定义一个名为 barChart 的 Action -->
<action name="barChart" class="com.jfreechart.action.BarChartAction" method="barChart">
<result type="chart">
/BarChart.jsp
<!-- 定义 JFreeChart 报表的大小 -->
<param name="width">800</param>
<param name="height">500</param>
</result>
</action> </package>
</struts>
(3)修改在web项目中的WebRoot/WEB-INF/目录下的web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<!-- 设置struts 2过滤器 -->
<filter>
<filter-name>struts 2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts 2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 设置欢迎页面 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- session超时定义,单位为分钟 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
(4)在web项目中的src目录下新建包: com.jfreechart.commons , 在该包中新建类 FileUtil.java
FileUtil.java
package com.jfreechart.commons;
import javax.servlet.ServletContext;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
public class FileUtil {
/**
* 获得web项目根目录
*/
public static String getWebRootPath() throws Exception {
ActionContext actionContext = ActionContext.getContext();
ServletContext servletContext = (ServletContext)actionContext.get(ServletActionContext.SERVLET_CONTEXT);
String rootPath = servletContext.getRealPath("/");
return rootPath;
}
}
(5)在web项目中的WebRoot/目录下新建index.jsp、BarChart.jsp
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>首页</title>
</head>
<body>
<a href="barChart.action">查看柱状图</a><br />
</body>
</html>
BarChart.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>柱状图</title>
</head>
<body>
<img src="<s:property value="#request.filePath" />" />
</body>
</html>
完成以上步骤后,把项目部署到服务器,在浏览器中访问该项目的index.jsp文件,点击“查看柱状图”的链接,即可跳转到BarChart.jsp页面,柱状图图表就显示在BarChart.jsp页面上了,图表的效果如上图一致。另外,上述所用的方法是 把图表先生成一个jpg文件,存放在服务器上的该web项目的相关目录下,然后在前台的jsp页面中引用该文件在项目中的的文件路径,即可把图表显示到前台页面中