这两天在做项目,做性能监控的时候需呀用图表来直观的显示。选择了jfreechart。
中间遇到了不少的问题,但是经过两天的尝试,问题都被解决了。
jfreechart用到的jar包网上都有。
首先把servlet代码显示如下:
package com.pzoom.crabman.servlet;
import java.awt.Rectangle;
import java.awt.Shape;
import java.io.CharArrayWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.StandardEntityCollection;
import org.jfree.chart.imagemap.ImageMapUtilities;
import org.jfree.chart.imagemap.OverLIBToolTipTagFragmentGenerator;
import org.jfree.chart.imagemap.StandardToolTipTagFragmentGenerator;
import org.jfree.chart.imagemap.StandardURLTagFragmentGenerator;
import org.jfree.chart.imagemap.ToolTipTagFragmentGenerator;
import org.jfree.chart.labels.StandardPieToolTipGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.servlet.ServletUtilities;
import org.jfree.chart.urls.StandardPieURLGenerator;
import com.pzoom.crabman.util.ChartUtil;
public class CharServlet extends HttpServlet {
public CharServlet() {
super();
}
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
Shape shape = new Rectangle(20, 10);
ChartEntity entity = new ChartEntity(shape);
StandardEntityCollection coll = new StandardEntityCollection();
coll.add(entity);
//该工具类上面没有介绍,在鼠标移动到图片时显示提示信息是用Map实现的,这些Map是用该类生成的。
ChartRenderingInfo info = new ChartRenderingInfo(coll);
PrintWriter pw=response.getWriter();//输出MAP信息
//CharArrayWriter cawMap = new CharArrayWriter();
//PrintWriter pwMap = new PrintWriter(cawMap);
JFreeChart chart = null;
boolean useOverLibForToolTips = true;
ToolTipTagFragmentGenerator toolTipTagFragmentGenerator = null;
if (useOverLibForToolTips) {
toolTipTagFragmentGenerator = new OverLIBToolTipTagFragmentGenerator();
} else {
toolTipTagFragmentGenerator = new StandardToolTipTagFragmentGenerator();
}
//显示样式(是否为3D效果)
String style = request.getParameter("style");
String fileName = null; //生成图片的文件名
if(style != null && "3d".equals(style)){ //获取生成图片的名称
fileName = ServletUtilities.saveChartAsPNG(
ChartUtil.createChart(true), 500,300, request.getSession());
//ChartUtilities.writeImageMap(pw, fileName, info, false);
//System.out.println(ChartUtilities.getImageMap(, info));
request.setAttribute("fileName", fileName);
//pw.flush();
}else{
chart = ChartUtil.createChart(false);
//ChartUtilities.writeChartAsPNG(respon, chart, 500, 500, info);
fileName = ServletUtilities.saveChartAsPNG(
chart, 500, 500,info, request.getSession());
//注意,这个savesaveChartAsPNG方法的第四个参数,info,如果没有这个参数的话,是不能将图片的map存入的,也就是说生成的图片没有热点。。。
//ChartUtilities.writeImageMap(pw, fileName, info, false);
ChartUtilities.writeImageMap(pw, "chartMap",info,false); //这里的参数chartMap,意思是:把map信息写入request中key值为chartMap的map中。取出的时候,在页面上用getAttribute(“chartMap”)
//String sMap = cawMap.toString();
//String sMap = ChartUtilities.getImageMap(fileName, info);
// 获得"map"
String sMap = ImageMapUtilities.getImageMap("chartMap", info,
toolTipTagFragmentGenerator,
new StandardURLTagFragmentGenerator());
System.out.println(sMap);
request.setAttribute("sMap", sMap);//存储map信息。
request.setAttribute("chartMap", "chartMap");
request.setAttribute("fileName", fileName);
//pw.flush();
}
//获取图片的路径
String graphURL = request.getContextPath() + "/servlet/DisplayChart?filename=" + fileName; //将路径放到request对象中
//注意这里的"/servlet/DisplayChart?filename=" 是jfreechart的虚拟的存储路径。一定要与在web.xml中配置的servlet一致
request.setAttribute("graphURL", graphURL); //页面转发到result.jsp
request.getRequestDispatcher("result.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out
.println("<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
public void init() throws ServletException {
}
}
下面把ChartUtil类的代码弄出来:
package com.pzoom.crabman.util;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.text.DecimalFormat;
import java.util.Random;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
public class ChartUtil {
//字体
private static final Font PLOT_FONT = new Font("宋体", Font.BOLD, 15);
public static CategoryDataset createDataSet() {
//图例名称
String[] line = { "JAVA", "C#", "C++" };
//类别
String[] category = { "2000年","2001年","2002年", "2003年", "2004年" };
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;
}
public static JFreeChart createChart(boolean is3D) {
JFreeChart chart = null;
if(is3D){
chart = ChartFactory.createLineChart3D(
"2000-2004年优秀程序员数量统计", //图表标题
"程序开发语言", //X轴标题
"程序员数量", //Y轴标题
createDataSet(), //绘图数据集
PlotOrientation.VERTICAL, //绘制方向
true, //显示图例
true, //采用标准生成器
false //是否生成超链接
);
}else{
chart = ChartFactory.createLineChart("2000-2004年优秀程序员数量统计",
//图表标题
"程序开发语言",
//X轴标题
"程序员数量",
//Y轴标题
createDataSet(),
//绘图数据集
PlotOrientation.VERTICAL,
//绘制方向
true,
//是否显示图例
true,
//是否采用标准生成器
false
//是否生成超链接
);
}
//设置标题字体
chart.getTitle().setFont(new Font("隶书", Font.BOLD, 23));
//设置图例类别字体
chart.getLegend().setItemFont(new Font("宋体", Font.BOLD, 15));
chart.setBackgroundPaint(new Color(192,228,106));
//设置背景色
//获取绘图区对象
CategoryPlot plot = chart.getCategoryPlot();
plot.getDomainAxis().setLabelFont(PLOT_FONT);
//设置横轴字体
plot.getDomainAxis().setTickLabelFont(PLOT_FONT);//设置坐标轴标尺值字体
plot.getRangeAxis().setLabelFont(PLOT_FONT); //设置纵轴字体
plot.setBackgroundPaint(Color.WHITE); //设置绘图区背景色
plot.setRangeGridlinePaint(Color.RED); //设置水平方向背景线颜色
plot.setRangeGridlinesVisible(true); //设置是否显示水平方向背景线,默认值为true
plot.setDomainGridlinePaint(Color.RED); //设置垂直方向背景线颜色
plot.setDomainGridlinesVisible(true); //设置是否显示垂直方向背景线,默认值为false
//获取折线对象
LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
renderer.setShapesVisible(true);
renderer.setDrawOutlines(true);
renderer.setUseFillPaint(true);
renderer.setFillPaint(java.awt.Color.white);
//renderer.setToolTipGenerator(new StandardCategoryToolTipGenerator( "{2} ",new DecimalFormat()));//前面参数是标签,可以是{0},{1}或者{2},{2}代表数值,后面那个参数就是数据格式
BasicStroke realLine = new BasicStroke(1.6f); //设置实线
float dashes[] = { 8.0f }; //定义虚线数组
BasicStroke brokenLine = new BasicStroke(1.6f, //线条粗细
BasicStroke.CAP_SQUARE, //端点风格
BasicStroke.JOIN_MITER, //折点风格
8.f, //折点处理办法
dashes, //虚线数组
0.0f); //虚线偏移量
renderer.setSeriesStroke(1, brokenLine); //利用虚线绘制
renderer.setSeriesStroke(2, brokenLine); //利用虚线绘制
renderer.setSeriesStroke(3, realLine); //利用实线绘制
return chart;
}
}
然后是web.xml 里的配置:
<!-- 第一个servlet 是我自己写的用于接收页面发来的请求-->
<servlet>
<servlet-name>CharServlet</servlet-name>
<servlet-class>com.pzoom.crabman.servlet.CharServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CharServlet</servlet-name>
<url-pattern>/CharServlet</url-pattern>
</servlet-mapping>
<!-- 第二个servlet 是jfreechart的servlet,用于返回图片的-->
<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>/servlet/DisplayChart</url-pattern>
<!--注意这个url-patten与前面我说到的配置是一致的-->
</servlet-mapping>
最后是页面:
首先是index.jsp页面:发起请求.
<h1>查看统计报表</h1>
<a href="CharServlet">普通样式</a>
<a href="CharServlet?style=3d">3D样式</a>
然后是result.jsp页面:显示jfreechart生成的图片
<img src="${graphURL}" border="0" ismap="ismap" usemap="#chartMap"/> <br><br>
<%=request.getAttribute("sMap")%>
注:usermap="#chartMap" 也可以替换为usermap="#<%=request.getAttibute("chartMap")%>"
都行。
至此万事大吉。
但是运行后会出现,map没有出来,鼠标移动到节点时没有效果。
原来jfreechart需要调用一个js:overlib.js 直接在google中搜索。然后添加到项目中。
<script type="text/javascript" src="js/overlib.js"></script>
另外在补充一个问题,就是如果生成的图片或内容过多时会出项cannot forward afrter response has been commited ,如果你确定没有任何flush语句的话,那么你可以这样处理。response.setBufferSize(1024*100);
这是因为你的输出缓冲区太小,输入满之后,就会向外输出,这是系统就会提示response已被提交。
希望对有需要的朋友有用。如有错误,请不吝指正。十分感谢。