幾乎所有程式都需要輸出文本,無論是電子郵件、HTML 網頁、報表還是控制台日誌。然而,電腦本質上只能處理二進制資料,開發者必須透過程式碼將結構化資料轉為人類可讀的文本。傳統上,我們習慣在 Java 程式碼中直接拼接字串(如使用 StringBuffer 或 System.out.println),但這種方式存在嚴重缺陷:文本內容與業務邏輯強耦合,導致維護困難、非技術人員無法參與文案編輯,且結構調整極不靈活。
以發送客戶帳單郵件為例,若將郵件內容直接寫死在迴圈中:
for (int i = 0; i < customers.size(); i++) {
Customer customer = (Customer) customers.get(i);
StringBuffer message = new StringBuffer();
message.append("尊敬的先生/女士: ");
message.append(customer.getCustName());
message.append("\n\n");
message.append("您的帳戶餘額是 ");
message.append(customer.getAccountTotal());
message.append("\n\n");
message.append("致禮!\n某某裝飾品公司");
mm.sendMail(customer.getFirstName(), customer.getEmail(), "Account", message.toString());
}
這樣做會導致:
即使將字串提取為常數(static final String),非技術人員仍難以理解語法,且無法解決動態結構調整的問題。
模板引擎的核心思想是:將靜態文本結構(模板)與動態資料(模型)分離。開發者編寫純文本模板檔案,內含佔位符與簡單指令;引擎在執行時解析模板,注入資料並輸出最終文本。這樣帶來三大優勢:
Apache Velocity 是成熟、開源的 Java 模板引擎(同類還有 FreeMarker、Thymeleaf)。以下展示如何用 Velocity 重構上述郵件發送:
account_notice.vm尊敬的 $customer.custName 先生/女士: 您的帳戶餘額是 $customer.accountTotal 元。 致禮! 某某裝飾品公司
// 初始化 Velocity 引擎(通常在應用啟動時配置一次)
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.setProperty("resource.loader", "class");
velocityEngine.setProperty("class.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
velocityEngine.init();
// 發送郵件邏輯
Template template = velocityEngine.getTemplate("templates/account_notice.vm", "UTF-8");
for (Customer customer : customers) {
VelocityContext context = new VelocityContext();
context.put("customer", customer); // 直接放入領域物件,模板可透過 $customer.xxx 存取屬性
StringWriter writer = new StringWriter();
template.merge(context, writer);
mm.sendMail(customer.getFirstName(), customer.getEmail(),
"帳單通知", writer.toString());
}
Velocity 支援 #parse 引入公共片段(如頁首頁尾),實現模板模組化:
#parse("fragments/header.vm")
... 郵件主體 ...
#parse("fragments/footer.vm")
#if($customer.isVip) 尊貴的 VIP 客戶,$customer.custName 你好! #else 尊敬的 $customer.custName 先生/女士: #end #foreach($item in $customer.recentOrders) 訂單 $item.id:$item.amount 元(#dateFormat($item.date "yyyy-MM-dd")) #end
在 Context 中放入工具類(如 NumberFormat、DateFormat),或使用 Velocity Tools 提供的 $number.format、$date.format。
| 維度 | 字串拼接 | 模板引擎 |
|---|---|---|
| 文案維護 | 需開發者修改程式碼 | 業務人員直接編輯模板檔案 |
| 結構變更 | 重寫 Java 邏輯、重新編譯部署 | 修改模板即時生效 |
| 國際化支援 | 極其困難 | 對應語言建立不同模板檔案 |
| 測試驗證 | 需啟動應用、模擬資料 | 可獨立渲染模板預覽輸出 |
告別 StringBuffer.append() 的時代吧。引入模板引擎不僅能大幅提升開發效率,更能讓團隊專注於各自擅長的領域:開發者負責資料邏輯,業務人員掌控文案表達。Velocity、FreeMarker、Thymeleaf 等成熟方案任君選擇,核心原理相通——模板即文本,資料注入即渲染。下次需要生成郵件、報表、程式碼或配置檔時,請優先考慮模板引擎,你會發現它是 Java 文本生成的真正捷徑。