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

发布于 2024-08-16 16:51:38 字数 668 浏览 7 评论 0原文

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

This is the situation:
My 'metrics.jsp' page submits a couple variables that are needed to create the chart. The 'ProjectActionBean.java' calls down to a few other java classes that create the JFreeChart. I can display the chart in a pop-up but I want it to be displayed in the original browser window.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自我难过 2024-08-23 16:51:38

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

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

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

这将创建一个文件,您可以将其作为网页中的 提供。或者(但更高级),您可以使用 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,这些 URL 全部映射到同一个图表生成 servlet,但是在告诉 servlet 需要哪种图表的 URL。收到请求后,servlet 将执行 JFreeChart 魔法,然后使用 ChartUtilities.writeChartAsPNG() 将生成的图像转储到 servlet 的输出流。

I've written an application like this, so I can assure you it's feasible :)

First, you need to get rid of anything that's GUI. You simply don't have a GUI on the server. This means your ChartFrame frame gets dumped. My main routine for creating a chart looks like this:

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

This creates a file you can serve up as an <img> from your Web page. Alternatively (but a bit more advanced), you can use ChartUtilities to create a stream that you can serve up in response to a request for the image URL.

Another bit of magic that's required is to tell Java that you're running graphics code without a GUI. You need to set the environment variable

-Djava.awt.headless=true

For a Web app server like Tomcat, this goes into the Tomcat startup script.


Update

okay yeah doesn't the 'ChartUtilities.saveChartAsPNG();' just save the chart onto the file system? I want the user to be able to input the variables and then a chart be displayed directly back to them in the browser.

As long as you have just one user, writing the images to the file system will work fine for the scenario you describe. In fact, that's how my first version worked: I had 4 <img> tags in my HTML response page from the form where the user specified the parameters; and those pointed at the names of the 4 files with my images. So long as you finish writing those files before returning the answer to the user, this works fine.

Problems appear when you have multiple users. They can end up viewing the charts specified by the other user. There are possible workarounds with encoding the user's ID or session into the chart file names, but that gets ugly real fast. There is a better way, based on on-demand dynamic generation of each image, singly.

I don't know how much you know about HTML/HTTP, so I hope I'm not going to bore you with this:

For any given HTTP request, you can only return a single stream of data. Typically, that's a HTML page, i.e. a stream of text. If you want images in your HTML page, you insert <img> links with different URLs into your HTML page, and you're still just returning a page full of text. The browser then goes ahead and requests the images by firing off requests for those URLs mentioned in the <img> tags. This is pretty easy when your images are just files in the file system. If you want dynamically generated images such as charts, then you have to think up a URL for each kind of image you want to generate, and map each of those URLs to a servlet that knows how to generate such an image.

My app had 4 different charts on one page, so my HTML page had 4 <img> tags with 4 different URLs that all mapped to the same chart-generating servlet, but there were some parameters in the URL that told the servlet what kind of chart was wanted. Upon receiving the request, the servlet would do the JFreeChart magic and then it would use ChartUtilities.writeChartAsPNG() to dump the generated image to the servlet's output stream.

夜血缘 2024-08-23 16:51:38

您需要编写一个 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”标记。显然你可以向它传递参数等。

You need to write a servlet which writes image (byte stream) into the output stream to the client. There are no need for creating files. Basically something like this should work:

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

Then map it to some url in your web.xml and use from "img" tag in HTML/JSP. Obviously you can pass parameters to it etc.

小霸王臭丫头 2024-08-23 16:51:38

如果您想留在 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
        }
    }
}

If you want to stay within the Stripes framework you can use a custom extension of the StreamingResolution, thusly:

Create a new normal ActionBean implementation that will represent the URL of your chart (to be included in your img tag):

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

The custom StreamingResolution then looks like this:

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
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文