注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

无线时代辐射无穷

抓紧生宝宝,小心辐射

 
 
 

日志

 
 

FreeMarker基础教程  

2009-12-29 10:17:25|  分类: freemarker |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

在B/S程式设计中,常常有美工和程序员二个角色,他们具有不同专业技能:美工专注于表现——创建页面、风格、布局、效果等等可视元素;而程序员则忙于创建程式的商业流程,生成设计页面要显示的数据等等。

很多时候,要显示的资料在设计的时候并不存在,它们一般是在运行时由程式产生的,比如执行“价格不高于800NT的USB Disk”查询的返回结果。这种技术需求产生了JSP等Scriptlet,JSP十分强大,但是也常常被滥用,并导致一些不良的后果

  1. 将逻辑和表现混合在一起。
  2. 破坏了美工和程序员职责的正常分解。
  3. 使JSP页面难以阅读和维护。

模板引擎就是为了解决上面的问题而产生的。在设计HTML的时候,我们加入一些特定指令来指定要插入哪些数据,这些加了特殊指令的HTML或者其他文本,我们称为模板(Template)。而模板引擎会在输出页面时,用适当的数据替代这些代码。

模板和嵌入JSP的HTML是不同的,模板指令只有很有限的编程能力,可以避免混入商业逻辑。

三万英尺俯瞰FreeMarker

简单的说,FreeMarker就是一种用Java编写的模板引擎,它根据模板输出多种规格的文本。特别指出的是,FreeMarker与Web应用框架无关,它同样可以应用在非Web应用程序环境中。

下面我们来看看FreeMarker的模板:(product.ftl)

<html>  <head>   <title>Welcome!</title>  </head>  <body>   <h1>Welcome ${user}!</h1>   <p>Our latest product:   <a href="${latestProduct.url}">${latestProduct.name}</a>!  </body>  </html>

这个例子是在简单的HTML中加入了一些由${…}包围的特定代码,这些特定代码就是FreeMarker的指令。

至于user、latestProduct.url和latestProduct.name的具体内容则来自于数据模型(data model)。数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成。

模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型。

借助FMPP(FreeMarker PreProcessor)来运行FreeMarker

首先说明的是FreeMarker的运行并不依赖于FMPP。FMPP只是一个FreeMarker的辅助工具,有了它,我们可以快速地调试FreeMarker输出结果,而不需要借助Java编程,这可以大大地减轻美工设计人员的调试难度。你可以从:<" src="http://www.softleader.com.tw:8668/images/external-link.png"<http://fmpp.sourceforge.net/ 得到它。

在使用Freemaker的时候,我们需要下载相关的程序:

freemarker: <" src="http://www.softleader.com.tw:8668/images/external-link.png"<http://freemarker.sourceforge.net/

在磁盘上建立相关的文件夹:

D:/work/src/product.ftl  D:/work/out/  D:/work/data/product.tdd  D:/work/config.fmpp

我们使用的配置文件(config.fmpp)设置如下:

sourceRoot: src  outputRoot: out  logFile: log.fmpp  modes: [   copy(common/**/*.*, resource/*.*)   execute(*.ftl)   ignore(templates/*.*, .project, **/*.xml, xml/*.*, *.js)  ]  replaceExtensions: [ftl, html]  sourceEncoding: gb2312  data: tdd(../data/product.tdd)

注意:"data: tdd(../data/product.tdd)" 指定了模板的数据源,TDD是fmpp支持的数据格式之一 ,关于TDD介绍可参阅fmpp文档,也可参看TDD。product.tdd内容是这样的:

{   user: "Big Joe"   latestProduct: {url: "products/greenmouse.html", name: "Green Mouse"}   }

现在在dos下执行(假设FMPP安装在D:/FMPP下):

D:/work/>D:/FMPP/bin/fmpp

最后的输出结果是这样的,存放在文件out/product.html中:

<html>  <head>    <title>Welcome!</title>  </head>  <body>    <h1>Welcome Big Joe!</h1>    <p>Our latest product:    <a href="products/greenmouse.html">green mouse</a>!  </body>  </html>

正如FreeMarker文档中所叙述的,FreeMarker的工作原理就是:

模板+数据=输出!

FreeMarker并不局限于生成html,甚至可以产生java代码,这仅仅取决于你如何设计模板而已。

现在有了FMPP这个强大工具,我们接下来可以快速学习FreeMarker的相关指令。let us go!

在FreeMarker模板中使用的三种基本对象类型:Scalars、Hashes 和Sequences。在解释这些对象类型之前,我们先来看看数据模型。

典型的数据模型是树型结构,可以有任意深的层次,比如说:

(root)    |    +- animals    |   |    |   +- mouse    |   |   |       |   |   +- size = "small"    |   |   |       |   |   +- price = 50    |   |    |   +- elephant    |   |   |       |   |   +- size = "large"    |   |   |       |   |   +- price = 5000    |   |    |   +- python    |       |       |       +- size = "medium"    |       |       |       +- price = 4999

这棵树上的每一片叶子在FreeMarker中就称为Scalars,用来存储单值。Scalars保存的值有两种类型:字符串(用引号括起,可以是单引 号或双引号)、数字(不要用引号将数字括起,这会作为字符串处理)、日期和boolean值。对scalars的访问要从root开始,各部分用“.”分 隔,如animals.mouse.price。

树的每一个分支关联一个唯一的查询名字,例如“mouse”,“elephant”,这些分支充当了其他对象(size,price)的容器,这种结构则称为Hashes,参考Hashes的TDD定义

Sequences的作用与Hashes类似,也可以充当其它对象的容器,只是不使用变量名字,而使用数字索引:

(root)    |    +- animals    |   |    |   +- (1st)    |   |   |    |   |   +- name = "mouse"    |   |   |    |   |   +- size = "small"    |   |   |    |   |   +- price = 50    |   |    |   +- (2nd)    |   |   |    |   |   +- name = "elephant"    |   |   |    |   |   +- size = "large"    |   |   |    |   |   +- price = 5000    |   |    |   +- (3rd)    |       |    |       +- name = "python"    |       |    |       +- size = "medium"    |       |    |       +- price = 4999

可以通过animals[0].name来访问相应的Scalars。参考Sequences的TDD定义

针对上面三种对象类型的操作,可以参看对象类型的各种操作

模板与指令

除了相关的文本外,在FreeMarker模板中可以包括下面三种特定部分:

  1. ${…}:称为插补(interpolations),FreeMarker会在输出时用实际值进行替代。
  2. 指令:也叫FreeMarker标记,与HTML标记类似,但用#开始(有些以@开始,在后面叙述)。
  3. 注释:包含在<#-- 和 -->(而不是<!--和-->)之间文本。

控制指令

if指令

if指令与大部分程式语言一样,也支持<#else if..>,不再赘述。

<#if animals.python.price < animals.elephant.price>    Pythons are cheaper than elephants today.  <#else>    Pythons are not cheaper than elephants today.  </#if>

list指令

list指令将遍历Sequences里的每一个元素。list指令有两个隐含的特殊变量:

  1. item_index 该变量将返回元素在Sequences里的索引值。
  2. item_has_next 该变量是boolean型,false表明该元素是Sequences里的最后一个元素。
<p>We have these animals:  <table border=1>    <tr><th>Id<th>Name<th>Price    <#list animals as being>    <tr><td>${being_index+1}<td>${being.name}<td>${being.price} Euros    </#list>  </table>

上面的模板可以依次列印出三种动物的名字和价格,being_index和being_has_next则是它的特殊变量。

可以用<#break>指令提前结束list循环。

switch指令

与其他语言的switch语句类似。

<#switch being.size>    <#case "small">       This will be processed if it is small       <#break>    <#case "medium">       This will be processed if it is medium       <#break>    <#case "large">       This will be processed if it is large       <#break>    <#default>       This will be processed if it is neither  </#switch>

注意事项

  1. FTL区分大小写,所以list是正确的FTL指令,而List不是;${name}和${NAME}是不同的
  2. Interpolation只能在文本中使用
  3. FTL标记不能位于另一个FTL标记内部。
  4. 注释可以位于FTL标记和Interpolation内部。
  5. 多余的空白字符会在模板输出时移除
  6. 可用[#if..]来替代<#if..>,避免于HTML标记混淆。
  评论这张
 
阅读(2815)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017