大多數程序都需要輸出一些文本,比如郵件消息、HTML文件或控制台輸出。但是,計算機本質上只能處理二進制數據,程序員必須讓軟件來生成可理解的文本。在這篇文章中,我要介紹的是在生成和輸出文本時,為何使用模板引擎能夠節省時間。你將了解模板的優點,如何針對不同的情形創建高效的模板。和System.println說再見!
雖然程序員可以很輕松地編寫出輸出文字信息的代碼(因為這畢竟是從Hello World范例學到的第一件事情),但通常而言,程序員不是寫作或組織文字信息(如郵件)的最佳人選。因此,我們常常讓市場部門或公關部門去做那些事情。但遺憾的是,即使對於最普通的郵件,編寫者也常常依賴程序輸出來完成任務。無論是對於郵件編寫者還是程序員,這種合作方式都很容易帶來誤解和造成失誤。
請看一個例子:一個Java程序從某個數據源收集一些客戶信息,通過email給公司的每一個客戶發送帳戶余額信息。下面是完成這個任務的Java程序(完整的示例程序代碼可以從本文最後下載):
for (int i=0; i
{
Customer customer = (Customer)customers.get(i);
StringBuffer message = new StringBuffer();
message.append ("尊敬的先生/女士: ");
message.append (customer.getCustName());
message.append ("n");
message.append ("n");
message.append ("您的帳戶余額是 ");
message.append (customer.getAccountTotal());
message.append ("n");
message.append ("n");
message.append ("致禮!");
message.append ("n");
message.append ("某某裝飾品公司");
// 發送email
mm.sendMail (customer.getFirstName(), customer.getEmail(),
"Account", message.toString());
}
上面的例子可謂發送消息最差勁的方法之一。由於消息嵌入到了程序代碼之中,如果沒有程序員的幫助,其他人幾乎不可能對消息進行編輯。同時,即使對於專業的程序員,如果他不了解代碼,要進行編輯也很困難。如果你預見了這些麻煩,把代碼寫成下面這種形式:
static public final String STR_HELLO="尊敬的先生/女士: ";
static public final String STR_MESSAGE="您的帳戶余額是 ";
static public final String STR_BEY="致禮!n某某裝飾品公司";
如果說上述代碼使得消息編輯更容易,那麼這種幫助也不會很多。很難要求一個不搞程序設計的人理解static和final的含義。此外,如果要改變消息的結構,上面這種代碼也不夠靈活。例如,人們可能要求你在郵件消息中加入更多來自數據源的信息,這時,你就得修改構造郵件的代碼,或許還要添加更多的static final String對象。
模板簡介
從文本文件裝入消息文本可以解決部分問題——但不能提供動態內容,而這對於系統來說是很重要的。你需要有一種方法把動態內容插入到預先編寫好的文本消息。但是,如果使用某種文本模板引擎,它就能夠幫助你完成所有復雜的工作。
模板引擎解決了把動態內容插入文本消息的問題。使用模板引擎時,我們不再把消息直接嵌入程序,而是創建一個包含文本內容的簡單文本文件,稱為“文本模板”。模板引擎解析文本模板,借助一些簡單的模板指令,把動態內容插入模板輸出結果。
我選擇的模板引擎是Jakarta Project的Velocity,但你可以任意選擇其他許多模板引擎之一。Velocity和WebMacro或許是當前功能最豐富、最受歡迎的兩個引擎,而且兩者都按照源代碼開放協議免費提供。雖然我在本文例子中使用Velocity,你可以方便地把這些例子移植到不同的模板引擎,只需遵照目標引擎的語法即可。
我們來看看用Velocity完成的email程序例子。要編譯和運行修改後的程序,你必須下載Velocity並把它加入到classpath。如果要讓email部分也能正常運行,你還需要JavaMail。
for (int i=0; i<customers.size(); i++)
{
Customer customer = (Customer)customers.get(i);
// 創建一個環境,並加入所有的對象
VelocityContext context = new VelocityContext();
context.put ("CustName",customer.getCustName());
context.put ("total", new Double (customer.getAccountTotal()));
context.put ("customer", customer );
// 解析模板,生成結果字符串
StringWriter message = new StringWriter();
template.merge(context, message);
// 發送email
mm.sendMail (customer.getFirstName(), customer.getEmail(),
"Account", message.toString());
}
本文示例代碼或素材下載