前言:
為什么要用模板?有了JSTL,還需要freemarker嗎?
模板技術與容器無關,同樣可以應用於非Web應用程序環境。ftl文件改動之后是不需要編譯的,這點不同於Jsp 。JSTL只能用在jsp中,修改了jsp,需要重新編譯,從而使用模板更有效率。
一、上手實例
1. 在WEB-INF/lib中放置freemarker.jar,新建一個Servlet,Hello.java
package com.fbysss.test.servlet; import java.io.IOException; import java.io.Writer; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import freemarker.core.Environment; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; /** * Servlet implementation class for Servlet: hello * */ public class Hello extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { static final long serialVersionUID = 1L; private Configuration cfg; /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#HttpServlet() */ public Hello() { super(); } /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Map root = new HashMap(); root.put("msg","你好,freemarker!"); root.put("intValue", 10); root.put("nullTag", "n"); Template template = cfg.getTemplate("test.ftl"); //response.setContentType("text/html;charset=gbk");//設定字符集,否則有漢字亂碼 Writer out = response.getWriter(); try { //1.用Enviroment Environment env = template.createProcessingEnvironment(root, out); env.setClassicCompatible(true); env.process(); //2.template.process(root, out);//兩種方法都可以 //out.flush();//清除緩沖區 } catch (TemplateException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub } /* (non-Javadoc) * @see javax.servlet.GenericServlet#init() */ public void init() throws ServletException { // TODO Auto-generated method stub super.init(); cfg = new Configuration(); cfg.setServletContextForTemplateLoading(getServletContext(),"WEB-INF/templates"); //cfg.setClassicCompatible(true);//處理空值為空字符串 } }
2.在WEB-INF/templates/下建立test.ftl文件
<!--#escape x as x!""--> <!--#setting classic_compatible=true--> <html> <head> <title>FreeMarker Example </title> </head> <body> ${msg} ${intValue} ${empty?default("empty Value")} ${empty!} ${newTag} ${nullTag} </body> </html> <!--/#escape-->
3.測試servlet,看到結果了,這里主要要注意亂碼和空值的處理。亂碼問題,把//response.setContentType("text/html;charset=gbk");注釋去掉即可。下面重點說說空值的處理。
二、空值處理
${empty}
如果empty標簽沒有在servlet中添加key或者值為null,會報錯 empty Value Expression newTag is undefined。
有人說這是個好的控制錯誤的機制,但本人不這么認為,因為空值太常見了,誰知道什么時候里面就成空值了?每個變量理論上都有可能。
難道每個變量都要加入一個判斷?就像struts中丑陋的<empty>標簽?既然是模板引擎,就要靈活,何必來那么多限制?
還好,freemarker至少提供了解決辦法,否則我只好選擇其它引擎了。
freemarker中空值的多種處理方法:
1.按照freemarker的規范,老老實實的判斷是否有空值,有空值怎么處理。這在某種時候是有用的。格式:${empty!"EmptyValue of fbysss"}
比如值為空時,你可以給出一個友好的說明,但是很多的變量都要這么說明,未免太麻煩了。
2.<#escape x as x!""></#escape>可以對所有的變量進行空值處理,這里是全部替換為空字符串。當然也可以替換為其它字符串。
如果其中某些變量不需要這種替換,可以加入<#noescape></#noescape>標簽。
3.屬性配置方法:
配置classic_compatible=true可以滿足一般需要。默認情況變量為null則替換為空字符串,如果需要自定義,寫上${empty!"EmptyValue of fbysss"}的形式即可
a.通過Configuration設置。Configuration cfg = new Configuration(); cfg.setClassicCompatible(true);//設置屬性
b.通過Eviroment設置。
Environment env = template.createProcessingEnvironment(root, out);
env.setClassicCompatible(true);
c.通過ftl設置:在ftl前加入<!--#setting classic_compatible=true-->,
d.通過Spring配置文件設置
e.class目錄下添加freemarker.properties文件:加入classic_compatible=true
(需要struts2或spring)
freemarker三目運算: ${ (type == 'SPOT') ?string('熱點詞','熱點搜索')} |