------------------------
前言:
????? 为什么要用模板?有了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);//处理空值为空字符串? ??
- ????????? ??
- ????}???? ??
- }??
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-->???
<!--#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配置文件设置
- <bean?id="freemarkerConfig"??
- ????class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">??
- ??<property?name="freemarkerSettings">??
- ????<props>??
- ??????<prop?key="classic_compatible">true</prop>??
- ????</props>??
- ??</property>??
- </bean>??
<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)
举一反三,其他属性也可以用类似方法进行设置。
?
?
转自:http://huxiao.iteye.com/blog/470927