前言:

      为什么要用模板?有了JSTL,还需要freemarker吗?

      模板技术与容器无关,同样可以应用于非Web应用程序环境。ftl文件改动之后是不需要编译的,这点不同于Jsp 。JSTL只能用在jsp中,修改了jsp,需要重新编译,从而使用模板更有效率。

一、上手实例

  1. 在WEB-INF/lib中放置freemarker.jar,新建一个Servlet,Hello.java
 

 
  
  1. package com.fbysss.test.servlet;   
  2.  
  3. import java.io.IOException;   
  4. import java.io.Writer;   
  5. import java.util.HashMap;   
  6. import java.util.Map;   
  7.  
  8. import javax.servlet.ServletException;   
  9. import javax.servlet.http.HttpServletRequest;   
  10. import javax.servlet.http.HttpServletResponse;   
  11.  
  12. import freemarker.core.Environment;   
  13. import freemarker.template.Configuration;   
  14. import freemarker.template.Template;   
  15. import freemarker.template.TemplateException;   
  16.  
  17. /**   
  18.  * Servlet implementation class for Servlet: hello   
  19.  *   
  20.  */   
  21.  public class Hello extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {   
  22.    static final long serialVersionUID = 1L;   
  23.    private Configuration cfg;   
  24.     /* (non-Java-doc)   
  25.      * @see javax.servlet.http.HttpServlet#HttpServlet()   
  26.      */   
  27.     public Hello() {   
  28.         super();   
  29.     }          
  30.        
  31.     /* (non-Java-doc)   
  32.      * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)   
  33.      */   
  34.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {   
  35.         Map root = new HashMap();   
  36.            
  37.         root.put("msg","你好,freemarker!");   
  38.         root.put("intValue", 10);   
  39.         root.put("nullTag""n");   
  40.            
  41.         Template template = cfg.getTemplate("test.ftl");   
  42.         //response.setContentType("text/html;charset=gbk");//设定字符集,否则有汉字乱码   
  43.         Writer out = response.getWriter();   
  44.  
  45.         try {   
  46.             //1.用Enviroment   
  47.             Environment env = template.createProcessingEnvironment(root, out);   
  48.             env.setClassicCompatible(true);   
  49.             env.process();   
  50.             //2.template.process(root, out);//两种方法都可以   
  51.  
  52.             //out.flush();//清除缓冲区   
  53.         } catch (TemplateException e) {   
  54.             // TODO Auto-generated catch block   
  55.             e.printStackTrace();   
  56.         }   
  57.            
  58.     }      
  59.        
  60.     /* (non-Java-doc)   
  61.      * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)   
  62.      */   
  63.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {   
  64.         // TODO Auto-generated method stub   
  65.     }          
  66.        
  67.  
  68.     /* (non-Javadoc)   
  69.      * @see javax.servlet.GenericServlet#init()   
  70.      */   
  71.     public void init() throws ServletException {   
  72.         // TODO Auto-generated method stub   
  73.         super.init();   
  74.         cfg = new Configuration();   
  75.            
  76.         cfg.setServletContextForTemplateLoading(getServletContext(),"WEB-INF/templates");   
  77.         //cfg.setClassicCompatible(true);//处理空值为空字符串   
  78.            
  79.     }      

2.在WEB-INF/templates/下建立test.ftl文件

 
  
  1. <!--#escape x as x!""-->       
  2. <!--#setting classic_compatible=true-->       
  3. <html>       
  4. <head>       
  5.   <title>FreeMarker Example </title>       
  6. </head>       
  7. <body>       
  8.   ${msg}       
  9.   ${intValue}       
  10.   ${empty?default("empty Value")}       
  11.   ${empty!}       
  12.   ${newTag}       
  13.   ${nullTag}       
  14. </body>       
  15. </html>       
  16. <!--/#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配置文件设置
 

 
  
  1. <bean id="freemarkerConfig" 
  2.     class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> 
  3.   <property name="freemarkerSettings"> 
  4.     <props> 
  5.       <prop key="classic_compatible">true</prop> 
  6.     </props> 
  7.   </property> 
  8. </bean> 

e.class目录下添加freemarker.properties文件:加入classic_compatible=true
(需要struts2或spring)

举一反三,其他属性也可以用类似方法进行设置。