JSP 設計初衷是分離 Java 開發與前端設計,但現實中設計師難駕馭 JSTL/EL/標籤庫,導致 Java 開發者兼寫視圖邏輯,代碼混雜難維護。本文提出「純 Servlet + Helper 物件」架構:以 Java 程式碼直接產出 HTML,封裝重複結構為可復用方法,實測可將視圖層代碼量縮減 2/3,維護成本大幅降低。
HTMLConstants (介面) ← HTML 字串常量集中管理
↑
HTMLWriter / HTMLFlexiWriter ← 低階 HTML 標籤輸出方法
↑
MadnessWriter (專案專用) ← 高階組件:頁首、選單、表單、表格、分頁...
↑
MadnessServlet (抽象基類) ← 統一請求前處理、安全檢查、Writer 工廠
↑
具體 Servlet (Picks, PicksAction, Admin...) ← 業務邏輯 + 視圖輸出
if/for 原生表達流程控制,元件重構為方法,易讀易改。protected void doBoth(HttpServletRequest req, HttpServletResponse resp,
HttpSession session, MadnessWriter out) throws IOException {
// 1. 取得業務物件 + 安全檢查
Player player = playerMan.select(session.getAttribute(PLAYER_ID), true);
boolean readOnly = isCutoffPassed() && !player.isAdmin();
// 2. 準備下拉選單資料
Team[] teams = teamMan.selectAll();
Map selectTeams = getDropDownMap(teams);
// 3. 輸出頁面骨架
out.printPreContent(null, out.SCRIPTFile("/js/picks.js"));
out.printMenu(URL_PICKS);
out.printBeginBox();
// 4. 成功提示
if ("true".equals(req.getAttribute(SUCCESS)))
out.printDIV("smallHeading", "球隊選擇已儲存。");
out.printDIV("reminder", "(提醒:Pick 20 代表最看好冠軍)");
// 5. 表單輸出:動態/唯讀自動切換
for (int i = 1; i <= 20; i++) {
String teamID = player.getPick(i);
if (!readOnly)
out.printSELECT(PICK + i, selectTeams, teamID);
else
out.print(selectTeams.getOrDefault(teamID, "(未選擇)"));
}
// 6. 右側球隊列表(委派私有方法)
doRegionList(teams, out);
// 7. 收尾
out.printEndBox();
out.printPostContent();
}
// 低階
void printDIV(String cssClass, String content);
void printSELECT(String name, Map options, String selectedKey);
String IMG(String src, int w, int h); // 回傳字串,可巢狀
// 高階
void printMenu(String currentUrl); // 自動跳過當前頁連結
void printBeginBox() / printEndBox(); // 統一框架結構
void printPreContent(String title, String headExtras);
void printPostContent();
頁面級權限用 request.isUserInRole() 或自訂介面,邏輯寫在 Servlet 內,動態靈活(如截止日期後開放檢視他人選擇)。
Writer 加入 printText(key) / text(key),支援缺失翻譯拋異常或回退預設語系,完全掌控行為。
子類化 MadnessWriter 覆寫樣式表路徑、結構性 HTML(Logo、邊框),Servlet 基類依條件實例化不同 Writer,業務 Servlet 零修改。
輸出 HTML 不縮排不影響瀏覽器渲染。除錯時看 Java 代碼結構即可定位佈局問題,比在混雜 JSP 中找缺標籤高效得多。必要時僅在關鍵處加 NL(換行常量)提升可讀性。
「簡單靈活的方法往往更好」。純 Servlet 視圖層以 Java 原生語法表達動態輸出,封裝復用單位為方法而非標籤,配合單一職責的 Writer 階層,實現高內聚、低耦合、易測試、易維護的 Web UI 架構。建議團隊在中小型專案、內部系統、Admin 後台優先嘗試,體驗「代碼即視圖」的掌控感。