记录-三步走FreeMarker Template学习

本文记录了作者学习FreeMarker模板引擎的全过程,从初步接触到搭建环境并实现HelloFreeMarker示例,再到解决自定义方法模型等问题,分享了学习心得与经验。

  学习Java模版引擎FreeMarker截至到现在20个小时,记录一下整个学习过程,发现学习中的问题,同时留下对FreeMarker最初时的认知,待假以时日项目组的数据和视图层分离使用FreeMarker的时侯不至于因为时间长了不知从何开始,又要重新走一步Hello FreeMarker的过程,又能够温故知新发现更多,更奇妙的东西。


j_0001.gifHello FreeMarker

 1.百度百科:FreeMarker http://baike.baidu.com/link?url=204dZtLs4TQhVPp2V_gFfJrv9EzewLu3R4AXHOWIhr9CLxbgnxu0AewyWDmoxWhqGtNH0Dk9PlF-Wpd-rLPpwa

   很牛,很强大,能做表现出,也能当工具使,Java语言编写的模版引擎且对Web容器无与依赖性。

 2.找一篇博文看看Iteye 曾Java著名社区

http://relive123-yahoo-com-cn.iteye.com/blog/818013

   基本了解FreeMarker基本写法,功能特性,怎么弄个Hello FreeMarker出来

 3.出自何门何派,官方网站走一圈

http://freemarker.org/index.html

   惊喜,有部分中文文档,窃喜,英文文档也很清晰可读。

 4.尝试我的Hello FreeMarker

  • 新建一个web工程,将freemarker.jar放置lib(classpath)目录

  • 配置web.xml文件,配置方式和普通的Servlet配置相同


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
< servlet >
         < servlet-name >freemarker</ servlet-name >
         < servlet-class >freemarker.ext.servlet.FreemarkerServlet</ servlet-class >
         < init-param >
             < param-name >TemplatePath</ param-name >
             < param-value >/</ param-value >
         </ init-param >
         < init-param >
             < param-name >NoCache</ param-name >
             < param-value >true</ param-value >
         </ init-param >
         < init-param >
             < param-name >ContentType</ param-name >
             < param-value >text/html</ param-value >
         </ init-param >
         < init-param >
             < param-name >template_update_delay</ param-name >
             < param-value >0</ param-value >
         </ init-param >
         < init-param >
             < param-name >locale</ param-name >
             < param-value >zh_CN</ param-value >
         </ init-param >
         < init-param >
             < param-name >default_encoding</ param-name >
             < param-value >UTF-8</ param-value >
         </ init-param >
         < init-param >
             < param-name >output_encoding</ param-name >
             < param-value >UTF-8</ param-value >
         </ init-param >
         < init-param >
             < param-name >date_format</ param-name >
             < param-value >yyyy-MM-dd</ param-value >
         </ init-param >
         < init-param >
             < param-name >time_format</ param-name >
             < param-value >HH:mm:ss</ param-value >
         </ init-param >
         < init-param >
             < param-name >datetime_format</ param-name >
             < param-value >yyyy-MM-dd HH:mm:ss</ param-value >
         </ init-param >
     </ servlet >

  注意:初始化的参数很多可以根据需要配置,或者在使用的时候在进行设置,在FreeMarker的帮助文档中写的很清楚。

195238806.png

  • 创建一个test1.html模版内容如下:

1
< div ><#assign v="hello freemarker"> ${v}</ div >
  • 部署web工程打开test1.html

    195551374.png

  • OK,模版就是这么搞定,关于更多的指令等信息有第二步的博文,也有第三步的官方清晰可读的文档。



    下面是在探索中的一些总结:

  • FreeMarker数据模型+模版==输入内容,可产生友好的表现

  • 数据模型有简单数据类型,Sequence类型(Java的List,Array),Hasher类型(Map, Bean等),总体概况数据模型是一棵树,保证数据以树的形式组织,从而就有个root的概念

  • 实际使用过程中遇到的问题有很好的页面异常信息显示,并仔细阅读文档都可以解决,注意留心每一个条目说明后的Note信息

  • 特性丰富:内置的特性strings,numbers,booleans,dates等;指令特性声明,导入,包含,循环,判断,分支,功能函数,表达式等高频率使用

  • 最后一条,学习一个没有接触过的东西,还是从Hello XX开始是一个良好的起端,另外与其在网上找各种帖子,代码段学习不如试试这三步,末了看看官方文档初学遇到的问题基本都有清晰的说明并且能够发现更多的东西。



j_0001.gif一个例子说明官方文档的优越性

   问题:自定义方法模型

   解决:官方文档中有TemplateMethodModel接口配合源代码模仿一个判断字符串A是否包含字符串B的方法

   源码:

   接口TemplateMethodModel继承TemplateModel接口;

   接口TemplateMethodModelEx继承了TemplateMethodModel接口;

   TemplateMethodModelEx接口的实现中有一个类是:SimpleMethodModel看看他的源码就豁然开朗知道如何去实现我们自己的SimpleMethodIsContainsModel类。

   类:

1
2
3
4
public  final  class  SimpleMethodModel  extends  SimpleMemberModel
     implements
     TemplateMethodModelEx,
     TemplateSequenceModel

   核心实现方法:


1
public  Object exec(List arguments)

   自己实现:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package  com.broncho.fm;
import  java.util.List;
import  freemarker.template.TemplateMethodModel;
import  freemarker.template.TemplateModelException;
@SuppressWarnings ( "deprecation" )
public  class  SimpleMethodIsContainsModel  implements  TemplateMethodModel {
     @Override
     public  Object exec(List arguments)  throws  TemplateModelException {
         if  (arguments.size() !=  2 ) {
             throw  new  TemplateModelException(
                     "template model arguments is wrong !" );
         }
         return  ((String) arguments.get( 0 )).contains((CharSequence) arguments
                 .get( 1 ));
     }
}

    用法测试:

    编写一个servlet和一个模版

    1.Servlet实现


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package  com.broncho.fm;
import  java.io.IOException;
import  java.util.HashMap;
import  java.util.Map;
import  javax.servlet.ServletException;
import  javax.servlet.http.HttpServlet;
import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;
import  freemarker.template.Template;
import  freemarker.template.TemplateException;
public  class  TestMethodServlet  extends  HttpServlet {
     private  static  final  long  serialVersionUID = -8862621014491094117L;
     private  Template template;
     public  TestMethodServlet() {
         super ();
     }
     public  void  destroy() {
         super .destroy();
     }
     public  void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         doPost(request, response);
     }
     public  void  doPost(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         response.setContentType( "text/html" );
         response.setCharacterEncoding( "UTF-8" );
         Map<String, SimpleMethodIsContainsModel> root =  new  HashMap<String, SimpleMethodIsContainsModel>();
         root.put( "iscontains" new  SimpleMethodIsContainsModel());
         try  {
             template.process(root, response.getWriter());
         catch  (TemplateException e) {
             e.printStackTrace();
         }
     }
     public  void  init()  throws  ServletException {
         try  {
             template = FreeMarkerTemplateFactory.getConfiguration(
                     this .getServletContext(),  "/" ).getTemplate( "block2.ftl" );
         catch  (IOException e) {
             e.printStackTrace();
         }
     }
}

      这里servlet依赖一个工具助手类


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package  com.broncho.fm;
import  javax.servlet.ServletContext;
import  freemarker.template.Configuration;
/**
  * Template Configuration
  *
  */
public  class  FreeMarkerTemplateFactory {
     public  static  Configuration cfg;
     public  static  void  init() {
         if  (cfg ==  null ) {
             cfg =  new  Configuration();
         }
     }
     public  static  Configuration getConfiguration(ServletContext servletContext,
             String path) {
         init();
         if  (path ==  null ) {
             path =  "/" ;
         }
         cfg.setServletContextForTemplateLoading(servletContext, path);
         return  cfg;
     }
}

    2.模版


1
2
3
4
5
6
< div >
         <#assign arg1="tomcat" arg2="cat">
         ${arg1} is contains ${arg2}
         < br />
         ${iscontains(arg1, arg2)}
     </ div >

    说明:root很重要,创建的SimpleMethodIsContainsModel对象要作为方法使用,而在模版在的方法名就是root这个hasher的key值。

    3.部署运行

203943988.png

   运行之后报一大堆错误,摘取前部分重点信息,可以看出模版中的部分信息输出,计算后的结果没有输出。

   上面这段异常提示信息的信息量足够大,这也是个人感觉FreeMarker很牛的一点。

   分析:

  • isContains方法的返回值是boolean类型,FreeMarker template不具备boolean自动转string;

  • 不能转还不能说FreeMarker template能力不行,接下来他给的解释说 boolean_format设置为true,false,恰好这是他默认的计算语言格式,这么一说就不能怪他了;

  • 还没完,他给了两个处理建议,一个是解决当前问题,另一个是解决此类转换的方法,更人性化的是他还给了如何写的例子,如:${myboolean?string('yes','no');

  • 至此,还有惊喜的是FreeMarker Template异常提示的位置相当精确,而且还具备从哪里开始错就在哪那里开始报的优秀品质。

  修改后的模版信息:

 

1
2
3
4
5
6
< div >
         <#assign arg1="tomcat" arg2="cat">
         ${arg1} is contains ${arg2}
         < br />
         ${iscontains(arg1, arg2)?string("true","false")}
     </ div >

   

   末尾:实际上官方的帮助文档这一点写的很清楚,唯一要做的是习惯读英文资料。



本文转自 secondriver 51CTO博客,原文链接:http://blog.51cto.com/aiilive/1332579,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值