`
杨胜寒
  • 浏览: 284725 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

FreeMarker中文手册:模板开发入门

阅读更多

转载自yshjava的个人博客主页 《FreeMarker中文手册:模板开发入门》

下一篇:《FreeMarker中文手册:模板一览

FreeMarker中文版手册由南磊翻译(译者联系方式为:nanlei1987@gmail.com 或http://weibo.com/nanlei1987),官网地址http://www.freemarker.org

 简介

FreeMarker 是一款模板引擎:一种基于模板的、用来生成输出文本(任何来自于HTML格式的文本用来自动生成源代码)的通用工具。它是为Java 程序员提供的一个开发包或者说是类库。它不是面向最终用户,而是为程序员提供的可以嵌入他们开发产品的一款应用程序。


FreeMarker的设计实际上是被用来生成HTML网页,尤其是通过基于实现了MVC(Model View Controller,模型-视图-控制器)模式的Servlet 应用程序。使用MVC 模式的动态网页的构思使得你可以将前端设计者(编写HTML)从程序员中分离出来。所有人各司其职,发挥其擅长的一面。网页设计师可以改写页面的显示效果而不受程序员编译代码的影响,因为应用程序的逻辑(Java 程序)和页面设计(FreeMarker 模板)已经分开了。页面模板代码不会受到复杂的程序代码影响。这种分离的思想即便对一个程序员和页面设计师是同一个人的项目来说都是非常有用的,因为分离使得代码保持简洁而且便于维护。


尽管FreeMarker 也有编程能力,但它也不是像PHP那样的一种全面的编程语言,而仅仅只是将Java程序准备的数据(比如SQL 查询),使用模板生成文本页面来呈现。


FreeMarker 不是Web 应用框架。它是Web 应用框架中的一个适用的组件,但是FreeMarker 引擎本身并不知道HTTP 协议或Servlet。它仅仅来生成文本。即便这样,它也非常适用于非Web 应用环境的开发。要注意的是,我们使用FreeMarker 作为视图层组件,是为给如Struts 这样的Model 2 框架提供现成的解决方案。


FreeMarker 是免费的,基于BSD 规则的许可。它是OSI 认证的开源软件。OSI 认证是开源倡议的认证标识。

 

 

模板 + 数据模型 = 输出

FreeMarker中文手册:模板 + 数据模型 = 输出

模板文件同样是静态的HTML 代码,但是除了这些HTML代码外,代码中还包括了一些FreeMarker 指令,这些指令就能够做到动态效果。

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

 

 

这个模板存放在Web 服务器上,看上去像是静态的HTML 页面。但是不管何时,只要有人访问这个页面时,FreeMarker 将会介入执行,然后动态转换模板,用最新的数据内容替换${…}中的部分(例如:用Big Joe 或者其他的访问者的用户名来代替${user}),生成普通的HTML 文本并发送结果到访问者的Web 浏览器中去显示。所以访问者的Web 浏览器会接收到类似于第一个HTML 示例的内容(也就是说,显示普通的HTML 文本而没有FreeMarker的指令),浏览器也不会感知到FreeMarker 在服务器端被调用了。模板文件本身(存储在Web 服务器端的文件)在这个过程中也不会改变什么,所以这个转换过程发生在一次又一次的访问中。这样就保证了显示的信息总是即时的。

数据模型

 

(root)
|
+- user = "Big Joe"
|
+- latestProduct
	|
	+- url = "products/greenmouse.html"
	|
	+- name = "green mouse"

 

 

生成的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 背后(确切的说是MVC 模式的背后)的重要思想就是表现逻辑和业务逻辑相分离。在模板只是处理显示问题,也就是视觉设计问题和格式问题。所准备要显示的数据(如用户名等)与FreeMarker 无关,这通常是使用Java 语言或其他目的语言来编写的。所以模板开发者不需要关心这些数值是如何计算出来的。事实上,在模板保持不变的同时,这些数值的计算方式可以完全发生变化。而且,除了模板外,页面外观发生的变化可以完全不触碰其他任何东西。当模板开发者和程序员是不同一个人的时候,分离带来的好处更是显而易见的。


FreeMarker(还有模板开发者)并不关心数据是如何计算的,FreeMarker 只是知道真实的数据是什么。模板能用的所有数据被包装成data-model 数据模型。数据模型的创建是通过已经存在的程序计算得到的。至于模板开发者,数据模型像是树状结构(比如硬盘上的文件夹和文件),正如本例中的数据模型,就可以如下形式来描述:(为了避免误解:数据模型并不是文本文件,上面所描述的只是一种数据模型的表现形式。它来自于Java 对象,但这会成为Java 程序员要面对的问题。)


比较之前你在模板中看到的${user}和${latestProduct.name}。作为一种比喻:数据模型就像计算机文件系统上的内容:根root 和latestProduct 对应目录(文件夹),user,url 和name 对应文件。url 和name 在latestProduct 目录中,所以latestProduct.name 就像是说latestProduct 目录的name 一样。但是我所说的,这仅仅是个比喻,这里并没有真实的文件和目录。

 

概括地讲,模板和数据模型是FreeMarker 所需,并用来生成输出内容的(比如之前展示的HTML):模板+数据模型=输出。

 

数据模型一览

 

正如你看到的,数据模型基本结构是树状的。这棵树可以复杂而且有很大的深度,比如:

 

上面的数据模型中变量扮演目录的角色(根root,user,latestProduct)被称为hash 哈希表,哈希表通过可查找的名称(例如:”user”, ”latestProduct”)来访问存储在其中的变量。


如果要在模板中使用子变量,那应该从根root 开始指定它的路径,每级之间用点来分隔。要访问url的话,应该从根开始,先是latestProduct,然后是url,所以应该这样写:latestProduct.url。当放置${…}这种特定代码在表达式的前后时,我们就告诉FreeMarker 在那个位置上要来输出对应的文本。
sequences 序列也是一种非常重要的变量,它们和哈希表变量相似,但是它们不存储所包含变量的名称,而是按顺序存储子变量。这样,就可以使用数字索引来访问这些子变量。在如下这种数据模型中,animal 和whatnot.fruits 就是序列:
可以使用数组的方括号方式来访问一个序列的子变量。索引从零开始(从零开始是程序员写代码的传统习惯),那么就意味着序列第一项的索引是0,第二项的索引是1,并以此类推。要得到第一个动物的名称的话,那么就应该这么写代码:animals[0].name。要得到whatnot.fruits(就是”banana”这个字符串)的第二项,那么就应该这么来写:whatnot.fruits[1]。

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

 

标量可以分为如下类别:
字符串:这是文本类型,字符的任意序列,比如”m”,“o”,“u”,“s”,“e”这些,而且name 和size 也是字符串范畴。
数字:这是数字值类型,比如price 这些。在FreeMarker 中字符串”50”和数字50是两种完全不同的类型。前者只是两个字符的序列(这恰好是我们可以读的一个数字),而后者是一个可以在算数运算中直接被使用的数值。
日期/时间:这是时间日期类型。例如动物被捕捉的日期,或商店开始营业的时间。
布尔值:对应对/错(是/否,开/关等)这样仅仅代表正反的值。比如动物可以有一个受保护(protected)的子变量,这个变量存储这个动物是否被保护起来。

 

总结:
数据模型可以被看做是树状结构的。
标量存储单一的值,这种类型的值可以是字符串,数字,日期/时间或者是布尔值。
哈希表是存储变量和与其相关且有唯一标识名称变量的容器。
序列是存储有序变量的容器,存储的变量可以通过数字索引来检索,索引通常从零开始。

 

1
3
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics