| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| Applet/前端實時繪圖 | 實時性強、交互豐富 | JVM 啟動慢、繪圖慢、佔用客戶端資源、安全限制、瀏覽器已不支持 | 極少數高實時交互場景 (已淘汰) |
| Servlet 後台定時生成圖片文件 | 前端極快(靜態圖)、無客戶端依賴、可緩存/CDN 分發、服務端可控 | 非實時 (有延遲)、需存儲空間、併發寫入需鎖 | 絕大多數報表、儀表盤、監控大屏 |
| 現代方案:後端 API 返回 JSON + 前端 ECharts/Chart.js 渲染 | 關注點分離、交互豐富、跨平台、無插件 | 需前端圖表庫學習成本、大數據量渲染需優化 | 新項目首選 |
package com.example.report;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import com.sun.image.codec.jpeg.*;
public class ChartServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String filePath = "e:/temp/chart_balance_summary.jpg"; // 生產環境應配置化
try (FileOutputStream fos = new FileOutputStream(filePath)) {
// 1. 創建畫布
BufferedImage image = new BufferedImage(500, 300, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
// 2. 背景與抗鋸齒
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.WHITE);
g.fillRect(0, 0, 500, 300);
// 3. 繪製標題
g.setColor(Color.BLACK);
g.setFont(new Font("微軟雅黑", Font.BOLD, 18));
g.drawString("財務餘額摘要", 160, 30);
// 4. 繪製圖例 (模擬條形圖)
String[] labels = {"營運資金 %", "定期存款 %", "抵押貸款 %", "租賃 %"};
Color[] colors = {Color.DARK_GRAY, Color.YELLOW, Color.LIGHT_GRAY, Color.GREEN};
int[] values = {65, 45, 30, 55}; // 實際應從數據庫查詢
int barWidth = 30;
int gap = 40;
int startX = 80;
int baseY = 250;
int maxHeight = 180;
int maxValue = 100;
for (int i = 0; i < labels.length; i++) {
int x = startX + i * (barWidth + gap);
int height = values[i] * maxHeight / maxValue;
int y = baseY - height;
// 條形
g.setColor(colors[i]);
g.fillRect(x, y, barWidth, height);
// 數值標籤
g.setColor(Color.BLACK);
g.setFont(new Font("微軟雅黑", Font.PLAIN, 12));
g.drawString(values[i] + "%", x + 5, y - 5);
// 圖例
g.fillRect(x, baseY + 20, 12, 12);
g.drawString(labels[i], x + 18, baseY + 30);
}
// 5. 編碼輸出 JPEG
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
encoder.encode(image);
g.dispose();
// 6. 可選:直接輸出到響應流 (而非存文件)
// resp.setContentType("image/jpeg");
// JPEGImageEncoder respEncoder = JPEGCodec.createJPEGEncoder(resp.getOutputStream());
// respEncoder.encode(image);
} catch (Exception e) {
log("圖表生成失敗", e);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "圖表生成異常");
}
}
}
@Scheduled 或 Quartz 定期生成圖片到 Nginx 靜態目錄,前端直接 `
`,零 Java 請求開銷。「後台生成靜態圖片 + 前端靜態引用」是 Java Web 圖表展示的經典高性能模式。雖然現代項目多採用「API + 前端渲染」,但對於郵件嵌入、PDF 導出、大屏輪播、舊系統改造等場景,Servlet 服務端生成圖片依然是最穩健、部署最簡單的選擇。