WebWork (Struts 2 前身) 以攔截器鏈與結果類型機制支援多樣化視圖輸出。本文示範如何自訂 Result 類型 (ChartResult),在 Action 中構建 JFreeChart 物件,直接輸出 PNG 圖片至 HTTP Response,無需暫存檔案,實現「Action 即圖表服務」的乾淨架構。
webwork-2.2.jar, xwork-1.0.jar, ognl-2.6.jar, commons-logging.jarjfreechart-1.0.0.jar, jcommon-1.0.0.jarweb.xml 註冊 FilterDispatcher (WebWork 核心入口)
package pawpaw.test;
import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.Result;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartUtilities;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
public class ChartResult implements Result {
private JFreeChart chart;
private int width = 400;
private int height = 300;
// WebWork 會自動注入同名參數
public void setWidth(int width) { this.width = width; }
public void setHeight(int height) { this.height = height; }
public void setChart(JFreeChart chart) { this.chart = chart; }
@Override
public void execute(ActionInvocation invocation) throws Exception {
JFreeChart chartToRender = chart;
if (chartToRender == null) {
// 從 ValueStack 取得 (Action 的 getter 回傳)
chartToRender = (JFreeChart) invocation.getStack().findValue("chart");
}
if (chartToRender == null) {
throw new NullPointerException("No chart found in Action or Result config");
}
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("image/png");
try (OutputStream os = response.getOutputStream()) {
ChartUtilities.writeChartAsPNG(os, chartToRender, width, height);
}
}
}
500
350
package pawpaw.test;
import com.opensymphony.xwork.ActionSupport;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import java.awt.*;
public class ViewModerationChartAction extends ActionSupport {
private JFreeChart chart;
public String execute() throws Exception {
// 1. 準備資料
XYSeries series = new XYSeries("Random Walk");
for (int i = 0; i <= 100; i++) {
series.add(i, Math.random() * 100); // 模擬資料
}
XYSeriesCollection dataset = new XYSeriesCollection(series);
// 2. 建立圖表
NumberAxis xAxis = new NumberAxis("Raw Marks");
NumberAxis yAxis = new NumberAxis("Moderated Marks");
XYPlot plot = new XYPlot(dataset, xAxis, yAxis,
new StandardXYItemRenderer(StandardXYItemRenderer.LINES));
chart = new JFreeChart(
"Moderation Function",
JFreeChart.DEFAULT_TITLE_FONT,
plot,
false
);
// 3. 美化
chart.setBackgroundPaint(Color.WHITE);
Font titleFont = new Font("微軟正黑體", Font.BOLD, 18);
chart.setTitle(new TextTitle("Moderation Function", titleFont));
return SUCCESS;
}
// ChartResult 會透過此 getter 從 ValueStack 取得
public JFreeChart getChart() { return chart; }
}
DisplayChart
org.jfree.chart.servlet.DisplayChart
DisplayChart
/servlet/DisplayChart
本方案不需此 Servlet,直接串流輸出更高效。內建 Servlet 適合「生成圖片 → 存暫存檔 → HTML <img src='/servlet/DisplayChart?file=xxx'>」的間接模式。
https://host:port/app/viewModerationChart.action 直接顯示 PNG 圖片ChartUtilities.writeChartAsJPEG、writeChartAsSVG (需 Batik)Last-Modified/ETag 支援瀏覽器快取Struts 2 繼承 WebWork 架構,Result 介面兼容,僅套件名變更 (org.apache.struts2),配置檔改為 struts.xml,遷移成本極低。