4

情况是这样的:我的“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);
4

3 回答 3

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();' 只是将图表保存到文件系统中?我希望用户能够输入变量,然后在浏览器中直接显示一个图表。

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

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

我不知道你对 HTML/HTTP 了解多少,所以我希望我不会让你感到厌烦:

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

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

于 2009-12-29T15:47:28.877 回答
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”标签。显然,您可以将参数传递给它等。

于 2009-12-29T17:34:02.323 回答
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
        }
    }
}
于 2011-04-13T22:04:14.990 回答