如何在Stripes Framework的Web浏览器中显示JFreeChart

时间:2009-12-29 15:31:39

标签: java web-applications jfreechart stripes

情况如下: 我的'metrics.jsp'页面提交了创建图表所需的几个变量。 'ProjectActionBean.java'调用了一些创建JFreeChart的其他java类。我可以在弹出窗口中显示图表,但我希望它显示在原始浏览器窗口中。

JFreeChart placeChart = ChartFactory.createBarChart(
                                    "ChartName",
                "",             //x-axis label
                "",             //y-axis label
                dataset,
                PlotOrientation.VERTICAL,
                false,          //legend
                true,           //tooltype
                false);         //generate urls
        ChartFrame frame = new ChartFrame(name, placeChart);
        frame.pack();
        frame.setVisible(true);

3 个答案:

答案 0 :(得分:5)

我写了这样的应用程序,所以我可以向你保证这是可行的:)

首先,你需要摆脱任何GUI。您只是在服务器上没有GUI。这意味着您的ChartFrame frame被转储。我创建图表的主要例程如下:

  private void createChart(XYPlot plot, String fileName, String caption) throws IOException {
      JFreeChart chart = new JFreeChart(caption, plot);
      chart.addSubtitle(this.subtitle);
      if (plot.getRangeAxis() instanceof LogarithmicAxis) {
         chart.addSubtitle(1, new TextTitle("(logarithmische Skala)"));
      }
      File file = new File(fileName);
      file.delete();
      ChartUtilities.saveChartAsPNG(file, chart, CHART_WIDTH, CHART_HEIGHT);
   }

这会创建一个文件,您可以从网页上将其作为<img>提供。或者(但更高级),您可以使用ChartUtilities创建一个流,您可以提供该流以响应对图像URL的请求。

需要的另一个神奇之处就是告诉Java你在没有GUI的情况下运行图形代码。您需要设置环境变量

-Djava.awt.headless=true

对于像Tomcat这样的Web应用服务器,这将进入Tomcat启动脚本。


<强>更新

  

好的,是的,不是'ChartUtilities.saveChartAsPNG();'只需将图表保存到文件系统中?我希望用户能够输入变量,然后在浏览器中直接将图表显示回来。

只要您只有一个用户,将图像写入文件系统就可以适用于您描述的场景。事实上,这就是我的第一个版本的工作方式:我的HTML响应页面中有4个<img>标签,来自用户指定参数的表单;那些用我的图像指出了4个文件的名字。只要在将答案返回给用户之前完成这些文件的编写,这就可以了。

当您有多个用户时会出现问题。他们最终可以查看其他用户指定的图表。将用户的ID或会话编码到图表文件名中有可能的解决方法,但这很快就会变得难看。有一种更好的方法,基于每个图像的按需动态生成,单独使用。

我不知道你对HTML / HTTP有多了解,所以我希望我不会厌倦你:

对于任何给定的HTTP请求,您只能返回单个数据流。通常,这是一个HTML页面,即文本流。如果您想要HTML页面中的图片,则可以在HTML页面中插入包含不同网址的<img>个链接,并且仍然只返回一个充满文字的页面。浏览器然后继续并通过触发<img>标记中提到的那些URL的请求来请求图像。当您的图像只是文件系统中的文件时,这非常容易。如果您想要动态生成的图像(如图表),则必须考虑要生成的每种图像的URL,并将每个URL映射到知道如何生成此类图像的servlet。

我的应用程序在一个页面上有4个不同的图表,所以我的HTML页面有4个<img>标签,其中有4个不同的URL都映射到同一个图表生成servlet,但是URL中有一些参数被告知servlet需要什么样的图表。收到请求后,servlet将执行JFreeChart魔术,然后使用ChartUtilities.writeChartAsPNG()将生成的图像转储到servlet的输出流。

答案 1 :(得分:2)

您需要编写一个servlet,它将图像(字节流)写入到客户端的输出流中。无需创建文件。基本上这样的事情应该有效:

public class ChartServlet extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {

        JFreeChart chart = .. // create your chart
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ChartUtilities.writeChartAsPNG(bos, chart, width, height);

            response.setContentType("image/png");
            OutputStream out = new BufferedOutputStream(response.getOutputStream());
            out.write(bos.toByteArray());
            out.flush();
            out.close();
  }
}

然后将其映射到web.xml中的某个url,并使用HTML / JSP中的“img”标记。显然你可以将参数传递给它等。

答案 2 :(得分:1)

如果你想留在Stripes框架内,你可以使用StreamingResolution的自定义扩展,因此:

创建一个新的常规ActionBean实现,它将代表您的图表的URL(包含在您的img标记中):

@DefaultHandler
public Resolution view() {
    JFreeChart chart = ...
    return new ChartStreamingResolution(chart);
}

自定义StreamingResolution看起来像这样:

public class ChartStreamingResolution extends StreamingResolution {
    private JFreeChart chart;
    public ChartStreamingResolution(JFreeChart chart) {
        super("image/png");
        this.chart = chart;
    }

    @Override
    public void stream(HttpServletResponse response) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ChartUtilities.writeChartAsPNG(bos, chart, 400, 200);
            OutputStream out = new BufferedOutputStream(response.getOutputStream());
            out.write(bos.toByteArray());
            out.flush();
            out.close();
        } catch (Exception e) {
            //something sensible
        }
    }
}