FreeMarker的使用
FreeMarker是一個非常優秀的模板引擎,這個模板引擎可用于任何場景,FreeMarker負責將數據模型中的數據合并到模板中,從而生成標準輸出.界面開發人員只需要關于界面(也就是模板文件)的開發,而業務邏輯開發者只需要負責將需要顯示的數據填入數據模型-----FreeMarker負責合并數據模型和模板,從而生成標準輸出.?
FreeMarker特別適應于MVC模式的Web應用,雖然FreeMarker具有一些編程能力,但這種編程能力非常有限,無法實現業務邏輯,只能提供一些數據格式的轉換功能.因此,通常由Java程序準備要顯示的數據,由FreeMarker模板引擎來生成頁面,而FreeMarker模板則提供頁面布局支持.?
此外,FreeMarker也是與Web容器無關的,也就是FreeMarker并不一定需要運行在Web容器中:FreeMarker同樣可以應用于非Web應用程序環境.而且,FreeMarker并不是只能生成HTML頁面,它也可以生成各種文本,如XML,RTF,Java源代碼等.?
Struts2默認采用FreeMarker作為其模板文件,而Struts2所有的主題模板文件都是采用FreeMarker編寫的,eclipse中的JSP,Java等模板文件也是采用FreeMarker技術.?
1,在java程序中使用FreeMarker?
FreeMarker的模板就是一個.ftl文本文件,在該文件中使用了一些FreeMarker的特別標記,這些標記會動態顯示,或者控制程序輸出,如下面的模板文件代碼:?
${name},你好!${msg}?
這里類似于${}的就是動態的內容,稱作"插值".?
為了使用FreeMarker來將數據模型中的值合并到模板文件中,可按如下步驟進行:?
1,創建Configuration實例,該實例負責管理FreeMarker的模板加載路徑,負責生成模板實例?
2,使用Configuration實例來生成Template實例,同進需要指定使用的模板文件?
3,填充數據模型,數據模型就是一個Map對象?
4,調用Template實例的process方法完成合并.?
下面是一個使用FreeMarker創建輸出的Java程序,程序源代碼如下:?
package lee;?
import java.util.*;?
import java.io.*;?
import freemarker.template.*;?
public class HelloFreeMarker?
{?
??? private Configuration cfg;?
??? public void init() throws Exception?
{?
??????? //初始化FreeMarker配置?
??????? //創建一個Configuration實例?
??????? cfg = new Configuration();?
??????? //設置FreeMarker的模版文件位置?
??????? cfg.setDirectoryForTemplateLoading(new File("templates"));?
??? }?
????
public void process()throws Exception?
{?
??????? Map root = new HashMap();?
??????? root.put("name", "FreeMarker!");?
?? root.put("msg" , "您已經完成了第一個FreeMarker的示例");?
??????? Template t = cfg.getTemplate("test.ftl");?
??????? t.process(root, new OutputStreamWriter(System.out));?
}?
public static void main(String[] args)throws Exception?
{?
?? HelloFreeMarker hf = new HelloFreeMarker();?
?? hf.init();?
?? hf.process();?
}?
}?
上面的代碼創建了一個Map實例,這個Map將作為模板文件的數據模型,我們要使用FreeMarker必須導入freemarker.jar文件,FreeMarker的官網是http://freemarker.sourceforge.net/,雖然FreeMarker可以在Java程序中使用,但大部分時候還是用來生成HTML頁面.?
2,在Web應用中使用FreeMarker?
在Web應用中使用FreeMarker跟在Java程序中使用并沒有太大的區別.下面是是一個在Web中使用的例子,用來生成HTML頁面的模板文件內容如下:?
<html>?
<head>?
<title>FreeMarker的HelloWorld</title>?
</head>?
<body>?
${message}?
</body>?
</html>?
我們在Web應用中使用FreeMarker時,應該讓Servlet來合并模板和數據,因此,Servlet負責創建Configuration實例,并負責合并模板和數據,下面是Servlet源代碼:?
package lee;?
import java.util.*;?
import java.io.*;?
import javax.servlet.*;?
import javax.servlet.http.*;?
import freemarker.template.*;?
public class HelloServlet extends HttpServlet?
{?
??? private Configuration cfg;?
??? public void init()?
{?
??????? //初始化FreeMarker配置?
??????? //創建一個Configuration實例?
??????? cfg = new Configuration();?
??????? //設置FreeMarker的模版文件位置?
??????? cfg.setServletContextForTemplateLoading(getServletContext(), "WEB-INF/templates");?
??? }?
????
??? public void service(HttpServletRequest request, HttpServletResponse response)?
??????? throws ServletException, IOException?
{????????
??????? //建立數據模型?
??????? Map root = new HashMap();?
??????? root.put("message", "Hello FreeMarker!");?????
??????? //取得模版文件?
??????? Template t = cfg.getTemplate("test.ftl");????????
??????? // 開始準備生成輸出?
??????? // - 使用模版文件的charset作為本頁面的charset?
??????? // - 使用text/html MIME-type?
??????? response.setContentType("text/html; charset=" + t.getEncoding());?
??????? Writer out = response.getWriter();?
????????
??????? //合并數據模型和模版,并將結果輸出到out中?
??????? try?
?? {?
??????????? t.process(root, out);?
??????? }?
?? catch (TemplateException e)?
?? {?
??????????? throw new ServletException("處理Template模版中出現錯誤", e);?
??????? }?
??? }?
}?
可以看到這個Servlet類的代碼與普通的Java程序中使用FreeMarker大致一樣,區別有兩個:1,設置FreeMarker加載模板的方法不一樣,在Servlet中設置加載的方法是setServletContextForTemplateLoading,第一個參數是本web應用的ServletContext,第二個參數是模板文件的路徑.;2,結果必須輸出到HttpServletResponse中,才能被瀏覽器加載.?
配置Servlet的web.xml文件中的代碼如下:?
<web-app>?
<servlet>?
?? <servlet-name>hello</servlet-name>?
?? <servlet-class>lee.HelloServlet</servlet-class>?
</servlet>?
<servlet-mapping>?
?? <servlet-name>hello</servlet-name>?
?? <url-pattern>/hello</url-pattern>?
</servlet-mapping>?
</web-app>?
3,FreeMarker的模板文件?
從上面的例子可以看到FreeMarker的模板文件并不比HTML頁面復雜多少,FreeMarker模板文件主要由如下4個部分組成:?
1,文本:直接輸出的部分?
2,注釋:<#-- ... -->格式部分,不會輸出?
3,插值:即${...}或#{...}格式的部分,將使用數據模型中的部分替代輸出?
4,FTL指令:FreeMarker指定,和HTML標記類似,名字前加#予以區分,不會輸出?
下面是一個FreeMarker模板的例子,包含了以上所說的4個部分?
<html><br>?
<head><br>?
<title>Welcome!</title><br>?
</head><br>?
<body><br>?
<#-- 注釋部分 --><br>?
<#-- 下面使用插值 -->?
<h1>Welcome ${user} !</h1><br>?
<p>We have these animals:<br>?
<u1><br>?
<#-- 使用FTL指令 -->?
<#list animals as being><br>?
?? <li>${being.name} for ${being.price} Euros<br>?
<#list><br>?
<u1><br>?
</body><br>?
</html>?
FreeMarker的語法知識將在下一篇文章中介紹?
4,使用FreeMarker作為Struts2的視圖技術?
Struts2使用FreeMarker作為其默認的模板技術,因此Struts2對FreeMarker的支持非常良好,為了在Struts2中使用FreeMarker模板技術,只需要在struts.xml文件中進行簡單配置即可.?
4.1在FreeMarker模板中使用Struts2標簽?
在FreeMarker模板中使用標簽畢竟不同于在JSP頁面中使用標簽,因為FreeMarker不支持使用taglib指令來導入標簽庫.但Struts2為了在FreeMarker模板中使用標簽庫提供了額外的支持.可以按照下面的步驟進行:?
1,將系統所需要的標簽庫定義文件(.tld文件)復制到WEB-INF目錄下,對于Struts2,則是復制struts2-core-2.0.11.2.jar中的META-INF\struts-tags.tld文件?
2,在web.xml文件中啟動JspSupportServlet.為了啟動它,則應該在web.xml文件中增加如下配置片段:?
<!-- 定義一個JspSupportServlet -->?
<servlet>?
?? <servlet-name>JspSupportServlet</servlet-name>?
?? <servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>?
?? <!-- 配置JspSupportServlet優先啟動 -->?
?? <load-on-startup>1</load-on-startup>?
</servlet>?
3,在FreeMarker模板中使用assign指令導入標簽庫,導入標簽庫的代碼如下:?
<#-- 定義/WEB-INF/struts-tags.tld文件對應的標簽庫前綴為s -->?
<#assign s=JspTaglibs["/WEB-INF/struts-tags.tld"] />?
4,在FreeMarker模板中增加了標簽庫的定義之后就可以使用了,下面是在FreeMarker模板中使用標簽的代碼:
<#-- 在FreeMarker中使用Struts2標簽 -->?
<@s.form action="Login.action">?
<@s.textfield name="username" label="用戶名"/>?
<@s.textfield name="password" label="密碼"/>?
<@s.submit value="提交"/>?
</@s.form>?
如果是在JSP中使用Struts2標簽,則格式如下:?
<s:form action="Login.action">?
<s:textfield name="username" label="用戶名"/>?
<s:textfield name="password" label="密碼"/>?
<s:submit value="提交"/>?
</s:form>?
值得注意的是,我們不能通過瀏覽器直接訪問.ftl文件,否則將看到該模板頁面的源代碼,而不是我們想要的生成的HTML頁面.這是因為Web容器默認不會處理FreeMarker模板頁面.?
在Struts2框架下,Struts2框架充當了之前的Servlet角色,只要瀏覽器的請求經過Struts2處理后,Struts2都會自動加載FreeMarker模板,并使用數據模型來填充該模板,再將最后的HTML頁面輸出給客戶端.為了讓所有的用戶請求都經過Struts2的處理,這里將所有的FreeMarker模板放在WEB-INF\ftl目錄下.(WEB-INF目錄下的所有文件客戶端都是不能直接訪問的),因為瀏覽器無法訪問.ftl文件了,因此我們在struts.xml配置文件中增加如下配置:?
?? <!-- 配置匹配所有請求的Action -->?
??????? <action name="*">?
??????????? <result type="freemarker">/WEB-INF/ftl/{1}.ftl</result>?
??????? </action>?
國為增加了上面的配置,在瀏覽器中請求login.action的時候,該action會被轉向login.ftl模板.此時就可以看到返回的HTML頁面.?
4.2 使用FreeMarker的Result?
從前面我們可以看到,使用FreeMarker與使用JSP作為輸出文件并沒有太大區別,下面來看看剛才的應用中Action中的代碼:?
package lee;?
import com.opensymphony.xwork2.Action;?
import com.opensymphony.xwork2.ActionContext;?
public class LoginAction implements Action?
{?
??? private String username;?
??? private String password;?
??? public String getUsername()?
{?
??????? return username;?
??? }?
??? public void setUsername(String username)?
{?
??????? this.username = username;?
??? }?
??? public String getPassword()?
{?
??????? return password;?
??? }?
??? public void setPassword(String password)?
{?
??????? this.password = password;?
??? }?
public String execute() throws Exception?
{?
??????? if (getUsername().equals("scott")?
??????????????? && getPassword().equals("tiger") )?
?? {?
??? ActionContext.getContext().getSession().put("user" , getUsername());?
??????????? return SUCCESS;?
??????? }?
?? else?
?? {?
??????????? return ERROR;?
??????? }?
??? }?
}?
此Action在struts.xml文件中的配置如下:?
<action name="Login" class="lee.LoginAction">?
<result name="error" type="freemarker">/WEB-INF/ftl/error.ftl</result>?
<result name="success" type="freemarker">/WEB-INF/ftl/welcome.ftl</result>????????
</action>?
返回的成功頁面代碼如下:?
<html>?
??? <head>?
??????? <title>成功頁面</title>?
??? </head>?
??? <body>?
??????? 歡迎,${user},您已經登錄!<br>?
<a href="GetBooks.action">查看作者李剛已出版的圖書</a>?
??? </body>?
</html>?
可以看到這個成功頁面會將user變量中的內容讀出并顯示,實際上,該變量值將可以從多個地方取得,Struts2解析FreeMarker模板中變量的順序如下:?
1,FreeMarker模板內建的變量;?
2,ValueStack中的變量;?
3,ActionContext中的變量;?
4,HttpServletRequest中的屬性;?
5,HttpSession中的屬性;?
6,ServletContext范圍的屬性.?
FreeMarker模板的內建變量有如下幾個:?
1,stack:代表ValueStack本身,可通過如下方式來訪問其中的變量"${stack.findString('ognl expr')}"?
2,action:代表剛剛執行過的Action實例?
3,response:代表HpptServletResponse實例?
4,res:代表HpptServletResponse實例?
5,request:代表HpptServletRequest實例?
6,req:代表HpptServletRequest實例?
7,session:代表HpptSession實例?
8,application:代表ServletContext實例?
9,base:代表用戶請求的上下文路徑.?
4.3 FreeMarker中訪問Servlet/JSP范圍對象?
Struts2還為在FreeMarker模板中訪問Servlet/JSP范圍對象提供了支持,通過這種支持可以直接訪問這些變量.?
訪問application范圍內的屬性代碼如下:?
<#if Application.attributeName?exists>?
${Application.attributeName}?
</#if>?
也可以通過使用Struts2標簽來輸出,代碼如下:?
<@s.property value="${#application.attributeName}" />?
訪問session范圍內的屬性如下:?
<#if Session.attributeName?exists>?
${Session.attributeName}?
</#if>?
或?
<@s.property value="${#session.attributeName}" />?
訪問request范圍內的屬性如下:?
<#if Request.attributeName?exists>?
${Request.attributeName}?
</#if>?
或?
<@s.property value="${#request.attributeName}" />?
對于request,還可以訪問request的請求參數,如下:?
<#if Parameter.parameterName?exists>?
${Parameter.parameterName}?
</#if>?
或?
<@s.property value="${#parameter.parameterName}" />?
訪問ValueStack上下文參數,代碼如下:?
${stack.findValue('#myContextParam')}?
或?
<@s.property value="${#myContextParam}" />?
from:?https://kingpingping.iteye.com/blog/1158003
總結
以上是生活随笔為你收集整理的FreeMarker的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一篇很全面的freemarker 前端w
- 下一篇: freemarker 教程