简体   繁体   English

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

[英]How can I display a JFreeChart in web browser with Stripes Framework

This is the situation: My 'metrics.jsp' page submits a couple variables that are needed to create the chart. 情况就是这样:我的'metrics.jsp'页面提交了一些创建图表所需的变量。 The 'ProjectActionBean.java' calls down to a few other java classes that create the JFreeChart. 'ProjectActionBean.java'调用了一些创建JFreeChart的其他java类。 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);

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. 首先,你需要摆脱任何GUI。 You simply don't have a GUI on the server. 您只是在服务器上没有GUI。 This means your ChartFrame frame gets dumped. 这意味着您的ChartFrame frame将被转储。 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. 这将创建一个文件,您可以从网页中将其作为<img>提供。 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. 或者(但更高级),您可以使用ChartUtilities创建一个流,您可以提供该流以响应对图像URL的请求。

Another bit of magic that's required is to tell Java that you're running graphics code without a GUI. 需要的另一个神奇之处就是告诉Java你在没有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. 对于像Tomcat这样的Web应用服务器,这将进入Tomcat启动脚本。


Update 更新

okay yeah doesn't the 'ChartUtilities.saveChartAsPNG();' 好吧是啊不是'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; 事实上,这就是我的第一个版本的工作方式:我的HTML响应页面中有4个<img>标签,用户指定参数; and those pointed at the names of the 4 files with my images. 那些用我的图像指出了4个文件的名字。 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. 将用户的ID或会话编码到图表文件名中有可能的解决方法,但这很快就会变得难看。 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: 我不知道你对HTML / HTTP有多了解,所以我希望我不会厌倦这个:

For any given HTTP request, you can only return a single stream of data. 对于任何给定的HTTP请求,您只能返回单个数据流。 Typically, that's a HTML page, ie a stream of text. 通常,这是一个HTML页面,即文本流。 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. 如果您想在HTML页面中使用图像,则可以在HTML页面中插入带有不同URL的<img>链接,而您仍然只是返回一个充满文本的页面。 The browser then goes ahead and requests the images by firing off requests for those URLs mentioned in the <img> tags. 然后浏览器继续并通过发射过在提到的URL的请求请求图像<img>标签。 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. 如果您想要动态生成的图像(如图表),则必须考虑要生成的每种图像的URL,并将每个URL映射到知道如何生成此类图像的servlet。

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. 我的应用程序在一个页面上有4个不同的图表,因此我的HTML页面有4个带有4个不同URL的<img>标记,这些标记都映射到同一个生成图表的servlet,但是URL中有一些参数告诉servlet什么类型的图表被通缉。 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. 收到请求后,servlet将执行JFreeChart魔术,然后使用ChartUtilities.writeChartAsPNG()将生成的图像转储到servlet的输出流。

You need to write a servlet which writes image (byte stream) into the output stream to the client. 您需要编写一个servlet,它将图像(字节流)写入到客户端的输出流中。 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. 然后将其映射到web.xml中的某个URL,并使用HTML / JSP中的“img”标记。 Obviously you can pass parameters to it etc. 显然你可以传递参数等。

If you want to stay within the Stripes framework you can use a custom extension of the StreamingResolution, thusly: 如果你想留在Stripes框架内,你可以使用StreamingResolution的自定义扩展,因此:

Create a new normal ActionBean implementation that will represent the URL of your chart (to be included in your img tag): 创建一个新的常规ActionBean实现,它将表示您的图表的URL(包含在您的img标记中):

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

The custom StreamingResolution then looks like this: 然后自定义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
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM