當(dāng)今的頁面展示技術(shù)主要分為兩種:基于JSP和EL表達(dá)式、采用模板引擎(FreeMarker、Velocity等)。 FreeMarker是一個用java語言編寫的模板引擎,它基于模板生成文本輸出。它強(qiáng)制將展示層和業(yè)務(wù)邏輯層分開,使開發(fā)人員不能像JSP頁面那樣在頁面中添加業(yè)務(wù)邏輯。
FreeMarker采用${…}的語法形式在模塊中充當(dāng)占位符,運(yùn)行時,由模板引擎解析模板,并用動態(tài)數(shù)據(jù)替換${…}部分的內(nèi)容。FreeMarker不僅可以用作表現(xiàn)層的實現(xiàn)技術(shù),還可以生成XML、Jsp和Java文件等。
FreeMarker模板主要由四部分組成 :
◆普通文本
◆注釋 <#--注釋內(nèi)容-->
◆插值:${..}和#{..}。
◆FTL標(biāo)簽。FTL標(biāo)簽的名字以#開始,如:<#if user=“admin”>…</#if>;自定義標(biāo)簽使用@代替#。
一、使用FreeMarker作為Struts2表現(xiàn)層的示例
- package com.action.convention;
-
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Result;
- import com.opensymphony.xwork2.ActionSupport;
-
- @Result(name = "success", location = "/freemarker.ftl")
- public class HelloAction extends ActionSupport {
-
- public String execute() {
- System.out.println("execute");
- return SUCCESS;
- }
-
- public List<String> getList() {
- List<String> list = new ArrayList<String>();
- list.add("aaa");
- list.add("bbb");
- list.add("ccc");
- list.add("ddd");
- return list;
- }
- }
freemarker.ftl
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>Insert title here</title>
- </head>
- <body>
- This is my first freemarker page!
- <br/>
- <#--循環(huán)list里的內(nèi)容-->
- <#list list as item>
- ${item}
- </#list>
- </body>
- </html>
生成的頁面如下:

二、使用FreeMarker模板生成Action示例
為了使用FreeMarker來將數(shù)據(jù)模型中的值合并到模板文件中,可按如下步驟進(jìn)行:
1,創(chuàng)建Configuration實例,該實例負(fù)責(zé)管理FreeMarker的模板加載路徑,負(fù)責(zé)生成模板實例
2,使用Configuration實例來生成Template實例,同進(jìn)需要指定使用的模板文件
3,填充數(shù)據(jù)模型,數(shù)據(jù)模型就是一個Map對象
4,調(diào)用Template實例的process方法完成合并
- private static void createAction() throws Exception {
- // 第一步:創(chuàng)建freemarker.template.Configuration實例
- Configuration cfg = new Configuration();
- File directory = new File("src/resources/template");
- // 指定.ftl模板路徑
- cfg.setDirectoryForTemplateLoading(directory);
-
- // 第二步:使用Configuration實例來生成Template實例,同進(jìn)需要指定使用的模板文件
- String tempFile = "action.ftl";
- Template template = cfg.getTemplate(tempFile);
-
- // 第三步:填充數(shù)據(jù)模型,數(shù)據(jù)模型就是一個Map對象
- LoginUser user1 = new LoginUser();
- user1.setUsername("Cui");
- user1.setPassword("1212");
- Map<String, Object> map = new HashMap<String, Object>();
- map.put("user", user1);
-
- // 第四步:調(diào)用Template實例的process方法完成合并
- Writer writer = new FileWriter("./bin/createAction.java");
- template.process(map, writer);
- }
action.ftl模板內(nèi)容如下:
- import com.opensymphony.xwork2.ActionSupport;
-
- public class ${user.username}Action extents ActionSupport{
- public String execute() {
- System.out.println("${user.password}");
- return SUCCESS;
- }
- }
運(yùn)行測試方法createAction()在指定路徑下生成createAction.java文件,文件內(nèi)容如下:
import com.opensymphony.xwork2.ActionSupport;
public class CuiAction extents ActionSupport{
public String execute() {
System.out.println("1212");
return SUCCESS;
}
}
可見,用user對象的值填充了freemarker文件中的占位符。
PS:在上面的示例完成后又在工程下做了一些其他的示例,這兩天學(xué)習(xí)FreeMarker重新運(yùn)行第一個示例時FreeMarker卻報錯了,提示無法獲取list變量,錯誤信息如下:
把list放入Session中可以正常顯示,但是手動把變量放入Session中不僅麻煩session也會越來越大,這樣肯定不能解決問題。重新創(chuàng)建了一個strut2工程,取消了struts-convention插件支持,測試成功,這讓我懷疑是struts-convention插件對FreeMarker的支持有問題,但寫這篇博客時做的示例就好好的。后來換到LoginAction下進(jìn)行測試,但是又發(fā)現(xiàn)一個問題:登錄form中的username和password無法通過屬性驅(qū)動傳遞到LoginAction的username和password屬性中,提取參數(shù)并將參數(shù)傳遞給Action屬性的工作是由param攔截器實現(xiàn)的,難不成param攔截器出問題了?應(yīng)該也不會,上網(wǎng)搜了一下發(fā)現(xiàn)http://topic.csdn.net/u/20110213/14/59b09329-b292-4164-a0fa-e2e6d7fa20d8.html?65640中遇到的問題和我的一樣,他提到去掉AOP支持就可以正常傳值,這才想到自己前幾天做了一個Spring AOP的示例,把a(bǔ)pplicationContext.xml中關(guān)于AOP的配置去掉,頁面到Action的傳值成功,Action中的屬性傳值給FreeMarker模板也成功了。關(guān)于Spring AOP造成傳值失敗需要再查找一下。