Java 如何在带Stripes框架的web浏览器中显示JFreeChart

Java 如何在带Stripes框架的web浏览器中显示JFreeChart,java,web-applications,jfreechart,stripes,Java,Web Applications,Jfreechart,Stripes,情况就是这样: 我的“metrics.jsp”页面提交了创建图表所需的两个变量。“ProjectActionBean.java”调用了其他几个创建JFreeChart的java类。我可以在弹出窗口中显示图表,但我希望它显示在原始浏览器窗口中 JFreeChart placeChart = ChartFactory.createBarChart( "ChartName", "",

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

我已经写了这样一个应用程序,所以我可以向您保证它是可行的:)

首先,你需要摆脱任何与GUI无关的东西。服务器上根本没有GUI。这意味着您的
图表框
将被转储。我创建图表的主要例程如下所示:

  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);
   }
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
        }
    }
}
这将创建一个文件,您可以从您的网页中用作
。或者(但更高级一点),您可以使用ChartUtilities创建一个流,以响应对图像URL的请求

另一个需要的魔法是告诉Java您正在运行没有GUI的图形代码。您需要设置环境变量

-Djava.awt.headless=true
对于像Tomcat这样的Web应用服务器,这会进入Tomcat启动脚本


更新


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

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

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

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

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


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

您需要编写一个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中使用from“img”标记。显然,您可以向它传递参数等。

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

创建一个新的普通ActionBean实现,该实现将表示图表的URL(包含在img标记中):

然后,自定义StreamingResolution如下所示:

  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);
   }
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
        }
    }
}

好的,是的,“ChartUtilities.saveChartAsPNG();”不是吗只需将图表保存到文件系统?我希望用户能够输入变量,然后在浏览器中直接向它们显示图表。用你提供给我的代码我能做到吗?谢谢你,阿洛托普,这就是我所说的“高级”选项。我将用一些提示更新我的答案。