【SpringMVC之FreeMark(一)】spring mvc中使用freemark的方法
模板技術在現代的軟體開發中有著重要的地位,而目前最流行的兩種模板技術恐怕要算freemarker和velocity了,webwork2.2對兩者都有不錯的支援,也就是說在webwork2中你可以隨意選擇使用freemarker或velocity作為view,模板技術作為view的好處是很多,尤其和jsp比較起來優點更大,眾所周知jsp需要在第一次被執行的時候編譯成servlet,那麼這個過程是很慢的,當然很多應用伺服器都提供預編譯的功能,但是在開發的時候仍然給我們程式設計師帶來了很多痛苦,每次修改都要多幾秒鐘,那在一天的開發中就有很多時間浪費在jsp的編譯上了。用webwork in action的作者的話來說:“每次修改之後重新執行都要等等幾秒是令人失望的,而頻繁地修改jsp更是會令你的失望情緒變本加厲“。我們把模板技術引入到view中去可以帶來更好的開發效率,而且模板的速度要比jsp快(雖然編譯過後的jsp在速度上已經滿足我的需求了,呵呵)。 當然模板技術可以用在很多領域,可不只在view那裡。我們可以通過模板技術來生成xml,生成jsp,生成java檔案等等,說到這裡,大家通常會使用模板技術用在公司的框架裡,這樣就可以很快速的生成添刪改查的程式碼,需要的只是模板,其他比如還有郵件模板等等。
以上是模板的作用,那麼現在開源的模板技術有好幾種,多了之後就有一個選擇的問題了,如何選擇一個滿足自己需要的模板的呢,寫了一個例子,我使用了幾種設計模式來完成了這個例子,這個例子中,同時使用了freemarker和velocity,這樣同學們可以通過程式碼很直觀的比較兩種模板技術,通過這個例子,我認識到freemarker在功能上要比velocity強大
1。在view層的時候,它提供了format日期和數字的功能,我想大家都有在頁面上format日期或數字的經驗,用jsp的同學可能對jstl的fmt標籤很有感情,使用了freemarker之後也可以使用freemarker提供的功能來formmat日期和資料,這個功能我想是很貼心的
2。通過我的使用我發現freemaker的eclipseplugin要比velocity的eclipseplugin好,好在很多地方呢,freemarker的外掛除了支援freemarker語法也支援html語句,而velocity的外掛貌似只支援velocity的語法,html就只是用普通的文字來顯示了,在這一點上freemarker佔上風了
3。freemarker對jsptag的支援很好,算了,不到迫不得已還是不要這樣做吧。
jsp的第一次執行,就要執行servlet,如果開發時頻繁的修改jsp,會導致開發速度比較慢;(每改一次,要重新編譯一次);
編譯過後,模板的速度也要比jsp快.
具體的freemark頁面上的使用:見http://blog.csdn.net/nengyu/article/details/6829244
最近做的專案中要在spring mvc中實現freemark 載入html模板,關鍵實現如下:
第一步:引入freemark.jar包
第二步:web.xml中的配置
<!-- freemarker 配置 --> <bean id="freeMarkerConfigurer" class="com.test.common.freemarker.CustomFreeMarkerConfigurer"> <!--freemark的配置檔案類--> <property name="templateLoaderPaths"> <list> <value>/WEB-INF/template/</value> <!--html檔案的存放位置--> </list> </property> <property name="freemarkerSettings"> <props> <prop key="template_update_delay">5</prop> <prop key="default_encoding">UTF-8</prop> <prop key="locale">zh_CN</prop> <prop key="url_escaping_charset">UTF-8</prop> <prop key="date_format">yyyy-MM-dd</prop> <prop key="time_format">HH:mm:ss</prop> <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop> <prop key="number_format">0.######</prop> <prop key="boolean_format">true,false</prop> <prop key="classic_compatible">true</prop> <prop key="whitespace_stripping">true</prop> </props> </property> </bean> <!-- freemark 頁面解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" /> <property name="contentType" value="text/html; charset=utf-8" /> <property name="exposeSpringMacroHelpers" value="true"/> <property name="cache" value="true" /> <property name="suffix" value=".html" /> <property name="order" value="1" /> </bean>
配置檔案類: com.test.common.freemarker.CustomFreeMarkerConfigurer
public class CustomFreeMarkerConfigurer extends FreeMarkerConfigurer { @Override protected TemplateLoader getAggregateTemplateLoader( List<TemplateLoader> templateLoaders) { <!-- HtmlTemplateLoader 這個類用來自定義html模板 --> return new HtmlTemplateLoader(super.getAggregateTemplateLoader(templateLoaders)); } }
第三步:在html中使用freemark標籤
<div onclick="showHideDiv('${corpUser.corpUserProblemInfo.corpUserId}')">
<#list corpUser.forbiddenInfoList as forbiddenRecord>
<#if forbiddenRecord_index<2>
<div>
<span>${forbiddenRecord.time} </span>
<span>${forbiddenRecord.remark}</span>
</div>
<#else>
<div name="hideDiv${corpUser.corpUserProblemInfo.corpUserId}" style="display: none">
<span>${forbiddenRecord.time} </span>
<span>${forbiddenRecord.remark}</span>
</div>
</#if>
</#list>
</div>
自定義html模板類:HtmlTemplateLoader,加escape html指令, escape指令在解析模版時起作用,而不是執行時起作用
public class HtmlTemplateLoader implements TemplateLoader { private static final String HTML_ESCAPE_PREFIX= "<#escape x as x?html>"; private static final String HTML_ESCAPE_SUFFIX = "</#escape>"; private final TemplateLoader delegate; public HtmlTemplateLoader(TemplateLoader delegate) { this.delegate = delegate; } /* (non-Javadoc) * @see freemarker.cache.TemplateLoader#closeTemplateSource(java.lang.Object) */ @Override public void closeTemplateSource(Object templateSource) throws IOException { delegate.closeTemplateSource(templateSource); } /* (non-Javadoc) * @see freemarker.cache.TemplateLoader#findTemplateSource(java.lang.String) */ @Override public Object findTemplateSource(String name) throws IOException { return delegate.findTemplateSource(name); } /* (non-Javadoc) * @see freemarker.cache.TemplateLoader#getLastModified(java.lang.Object) */ @Override public long getLastModified(Object templateSource) { return delegate.getLastModified(templateSource); } /* (non-Javadoc) * @see freemarker.cache.TemplateLoader#getReader(java.lang.Object, java.lang.String) * 在讀取template檔案之後, 在前後套上<#escape>標籤 */ @Override public Reader getReader(Object templateSource, String encoding) throws IOException { Reader reader = delegate.getReader(templateSource, encoding); String templateText = IOUtils.toString(reader); return new StringReader(HTML_ESCAPE_PREFIX+templateText + HTML_ESCAPE_SUFFIX); } }
escape指令body區的ftl的interpolations都會被自動加上escape表示式。但是不會影響字串內的interpolations。而且也只會影響到body內出現的interpolations,比如不會影響到include的ftl的interpolations。
<#escape x as x?html>
First name: ${firstName}
Last name: ${lastName}
Maiden name: ${maidenName}
</#escape>
等同於:
Last name: ${lastName?html}
Maiden name: ${maidenName?html} 具體的freemark指令見: freemarker學習筆記--指令參考: http://www.cnblogs.com/pengfeisun/articles/1623182.html