java 如何使用 Stripes Framework 在 Web 浏览器中显示 JFreeChart
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1975208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I display a JFreeChart in web browser with Stripes Framework
提问by robbie
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.
这是这种情况:我的“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);
回答by Carl Smotricz
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 framegets dumped. My main routine for creating a chart looks like this:
首先,您需要摆脱任何图形用户界面。您只是在服务器上没有 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);
}
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.
这将创建一个文件,您可以将其作为<img>Web 页面提供。或者(但更高级一点),您可以使用 ChartUtilities 创建一个流,您可以提供该流以响应对图像 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
另一个需要的魔法是告诉 Java 您正在运行没有 GUI 的图形代码。您需要设置环境变量
-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();' 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.
好吧是的不是'ChartUtilities.saveChartAsPNG();' 只是将图表保存到文件系统中?我希望用户能够输入变量,然后在浏览器中将图表直接显示回给他们。
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.
只要您只有一个用户,将图像写入文件系统将适用于您描述的场景。事实上,这就是我的第一个版本的工作方式:<img>我的 HTML 响应页面中有 4 个标签来自用户指定参数的表单;那些指向我的图像的 4 个文件的名称。只要您在将答案返回给用户之前完成这些文件的编写,就可以正常工作。
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.
当您有多个用户时会出现问题。他们最终可以查看其他用户指定的图表。有可能的解决方法是将用户的 ID 或会话编码到图表文件名中,但这很快就会变得很难看。有一个更好的方法,基于每个图像的按需动态生成,单独。
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. 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 stilljust returning a page full of text. The browser thengoes 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.
对于任何给定的 HTTP 请求,您只能返回单个数据流。通常,这是一个 HTML 页面,即文本流。如果您希望在 HTML 页面中显示图像,您可以将<img>具有不同 URL 的链接插入到您的 HTML 页面中,而您仍然只是返回一个充满文本的页面。浏览器然后继续并通过发射过在提到的URL的请求请求图像<img>标签。当您的图像只是文件系统中的文件时,这很容易。如果您想要动态生成的图像(例如图表),那么您必须为要生成的每种图像考虑一个 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. 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.
我的应用程序在一个页面上有 4 个不同的图表,所以我的 HTML 页面有 4 个<img>标签和 4 个不同的 URL,它们都映射到同一个图表生成 servlet,但是 URL 中有一些参数告诉 servlet 需要什么样的图表. 收到请求后,servlet 将执行 JFreeChart 魔术,然后将ChartUtilities.writeChartAsPNG()生成的图像转储到 servlet 的输出流。
回答by maximdim
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:
您需要编写一个 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();
}
}
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.
然后将它映射到 web.xml 中的某个 url 并使用 HTML/JSP 中的 "img" 标记。显然,您可以将参数传递给它等。
回答by rupjones
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
}
}
}

