首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Servlet 動態生成圖表最佳實踐:後台定時生成 + 前端靜態展示

     編輯:Java 程式設計入門

架構對比:為什麼不在前端實時生成?

方案優點缺點適用場景
Applet/前端實時繪圖 實時性強、交互豐富 JVM 啟動慢、繪圖慢、佔用客戶端資源、安全限制、瀏覽器已不支持 極少數高實時交互場景 (已淘汰)
Servlet 後台定時生成圖片文件 前端極快(靜態圖)、無客戶端依賴、可緩存/CDN 分發、服務端可控 非實時 (有延遲)、需存儲空間、併發寫入需鎖 絕大多數報表、儀表盤、監控大屏
現代方案:後端 API 返回 JSON + 前端 ECharts/Chart.js 渲染 關注點分離、交互豐富、跨平台、無插件 需前端圖表庫學習成本、大數據量渲染需優化 新項目首選

Servlet 生成 JPEG 圖片完整示例

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, "圖表生成異常");
        }
    }
}

生產環境關鍵優化點

  1. 定時任務 + 靜態文件:用 Spring @Scheduled 或 Quartz 定期生成圖片到 Nginx 靜態目錄,前端直接 ``,零 Java 請求開銷。
  2. 併發安全:生成臨時文件 → `Files.move(atomic)` 替換舊文件,避免讀寫衝突。
  3. 參數化圖表:URL 參數控制圖表類型/時間範圍,生成文件名含哈希,支持多版本共存。
  4. 字體部署:Linux 服務器需安裝中文字體 (如 `yum install fontconfig wqy-zenhei`),否則中文亂碼/方塊。
  5. 替代方案:考慮 JFreeChart (成熟圖表庫)、Apache Batik (SVG)、JavaFX Graphics (現代硬件加速) 替代手繪。

總結

「後台生成靜態圖片 + 前端靜態引用」是 Java Web 圖表展示的經典高性能模式。雖然現代項目多採用「API + 前端渲染」,但對於郵件嵌入、PDF 導出、大屏輪播、舊系統改造等場景,Servlet 服務端生成圖片依然是最穩健、部署最簡單的選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved