使用 FreeMarker 替換 JSP 的 10 個理由

ImportNew發表於2015-10-23

你還在使用 Java 伺服器頁面(俗稱JSP)嗎?我曾經也是,但是幾年前我拋棄了它們,並且再也沒有用過JSP了。JSP 是個很好的概念,但是它卻剝奪了 web 開發的樂趣。 對我而言,這些都是小事,比如無法在頁面模板上使用單獨的檔案header.jsp 和 footer.jsp,不能呼叫表示式語言的方法,在執行時無法合併,重新排列頁面的各個部分。所以我轉而使用 FreeMarker 模板。FreeMarker 已經存在一段時間了,如果你最近沒有關注過 FreeMarker 的話,那這有些建議給你,讓你考慮下個 web 應用使用 FreeMarker。

使用FreeMarker替換JSP的10個理由

1、類載入沒有 PermGen 問題

如果你已經開發Java Web應用程式一段時間,那麼對於 JVM 的 PermGen 問題可能並不陌生。由於 FreeMarker 模板不編譯成類,它們不佔用 PermGen 空間,並不需要一個新的類載入器載入。

2、模板載入器

直接從資料來源載入頁面和模板豈不是很好?也許從 CMS 或資料庫。也許你只想把它們放在一個地方,可以不重新部署整個應用程式就能更新它們。那麼在 JSP 中你是很難做到這一點的,但 FreeMarker 提供的模板載入器就是為了 這個目的。你可以使用內建類或者建立你自己的實現。

FreeMarker 也可以將多個載入器鏈在一起形成一個系列模板裝載器。我通常使用 WebappTemplateLoader 指向 WEB—INF 下一個內容資料夾。

Configuration configuration = new Configuration();
configuration.setTemplateLoader(
new WebappTemplateLoader(servletContext, "WEB-INF/content"));

3、可以在執行時嵌入模板

FreeMarker 能讓你建立真正的模板,而不只是片段 ,還記得 JSP 中的 header 和 footer 嗎?FreeMarker 允許你使用一個模板(在本例中為 head.ftl)

<head>
<title>${title}</title>
</head>

並將其新增到另一個模板(site.ftl body區域)。

<html>
${body}
</html>

可以以程式設計的方式選擇哪個模板進入 body 區。還可以新增多個模板一起放入同一區域。甚至可以將字串值或計算的值放入 body 區域。在 JSP 中試試做到這些。

4、沒有匯入

JSP 要求你匯入每個你需要使用的類,就像一個常規的 Java 類一樣。FreeMarker 模板,嗯,僅僅是模板。可以被包括在另一個模板中,但目前還不需要匯入類。

5、支援 JSP 標籤

使用 Jsp 的一個理由是有可用性很好的標籤庫。好訊息是 FreeMarker 支援 JSP 標籤。壞訊息是它們使用 FreeMarker 的語法,不是 JSP 語法。

6、表示式語言中的方法呼叫

除非你的目標是 Servlet 3.0/El 2.2 標準的容器,那麼表示式語言中方法呼叫是不可用的。不是所有人都同意 EL 表示式中方法呼叫是一件好事,但是當你需要它們的時候,使用 JSP 真的太痛苦了。 但是 FreeMarker 同等對待其中每個引用。

${customer.address.country}
${customer.getAddress().country}

7. 內建空字串處理

FreeMarker 和 Jsp 都可以在表示式語言中處理空值,但 FreeMarker 在可用性上更先進一些。

Invoice Date: ${(customer.invoice.date)!}

感嘆號告訴 FreeMarker 對錶達式自動檢查 null 值和空字串。如果 customer、invoice 或者 date 中有一個為空值或空字串,你只會得到標籤:

Invoice Date:

另一個選擇是感嘆號後包括你的預設值。

Invoice Date: ${(customer.invoice.date)!'No Invoice Available'}

如果所有值丟失,你會得到:

Invoice Date: No Invoice Available

請參見處理缺少的值瞭解更多細節。

8、共享變數

FreeMarker 的共享變數是我最喜歡的“隱藏”功能之一。此功能可以讓你設定自動新增到所有模板的值。 例如,可以設定應用程式的名稱作為共享變數。

Configuration configuration = new Configuration();
configuration.setSharedVariable("app", "StackHunter");

然後像任何其他變數一樣訪問它。

App: ${app}

在過去使用共享變數一般引用資源包 然後使用像 ${i18n.resourceBundle.key} 這樣的表示式來獲取值。

${i18n.countries.CA}
${i18n.countries['CA']}
${i18n.countries[countryCode]}

上面這些行都引用 countries_en.properties 資源包內的 key “CA”對應的值。你需要執行自己的 TemplateHashModel,然後將其新增為一個共享變數來實現這一目標。

9、支援 JSON

FreeMarker 內建 JSON 支援。 比方說你有以下的 JSON 儲存到變數命名 user 的字串中。

{ 'firstName': 'John', 'lastName': 'Smith', 'age': 25, 'address': { 'streetAddress': '21 2nd Street', 'city': 'New York', 'state': 'NY', 'postalCode': 10021 }}

使用 ?eval 將從字串轉換為一個 JSON 物件,然後像其他資料一樣在表示式中使用。

<#assign user = user?eval>
User: ${user.firstName}, ${user.address.city}

10、不只是為了 Web 開發

最後與 JSP 不同的是FreeMarker 模板可以在 servlet 容器之外使用。可以使用它們來生成電子郵件、 配置檔案、 XML 對映等。你甚至可以使用它們來生成 web 頁 並將它們儲存在伺服器端的快取中。 請在下一個 web 專案嘗試使用 FreeMarker把 web 開發的樂趣給找回來。

相關文章