作者:fbysss
关键字:FreeMarker

前言:

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

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

一、上手实例

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

 

 

 


 

二、空值处理

 

 

${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配置文件设置

<bean id="freemarkerConfig"
    class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
  <property name="freemarkerSettings">
    <props>
      <prop key="classic_compatible">true</prop>
    </props>
  </property>
</bean>


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

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

补充:

    我们在开发中,还经常发现这样的问题:

   页面中代码为${user.memo}但可能出现这样的情况:

   a.user == null

   b.user.memo == null

   上述简化方法也鞭长莫及了。

   也就是说,必须对上述两种情况都进行一下判断,才能保证页面不会报错。   
   这么简单的一个需求,代码却如此复杂,实在令人难以接受。

    还好,freemarker本身提供了这样的方法:

${(user.memo}!}或者${(user.memo}?if_exists}即可。

1. package
2. 
3. import
4. import
5. import
6. import
7. 
8. import
9. import
10. import
11. 
12. import
13. import
14. import
15. import
16. 
17. /**
18.  * Servlet implementation class for Servlet: hello
19.  *
20.  */
21. public class Hello extends javax.servlet.http.HttpServlet implements
22. static final long
23. private
24. /* (non-Java-doc)
25.      * @see javax.servlet.http.HttpServlet#HttpServlet()
26.      */
27. public
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
35. new
36.         
37. "msg","你好,freemarker!");
38. "intValue", 10);
39. "nullTag", "n");
40.         
41. "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. true);
49.             env.process();
50. //2.template.process(root, out);//两种方法都可以 
51. 
52. //out.flush();//清除缓冲区 
53. catch
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
64. // TODO Auto-generated method stub 
65.     }       
66.     
67. 
68. /* (non-Javadoc)
69.      * @see javax.servlet.GenericServlet#init()
70.      */
71. public void init() throws
72. // TODO Auto-generated method stub 
73. super.init();
74. new
75.         
76. "WEB-INF/templates");
77. //cfg.setClassicCompatible(true);//处理空值为空字符串 
78.         
79.     }   
80. }

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. default("empty Value")}
11.   ${empty!}
12.   ${newTag}
13.   ${nullTag}
14. </body>
15. </html>
16. <!--/#escape-->


3.测试servlet,看到结果了,这里主要要注意乱码和空值的处理。乱码问题,把//response.setContentType("text/html;charset=gbk");注释去掉即可。下面重点说说空值的处理。