freemarker(一)
1.模板+数据模型=输出
一个简单的HTML页面:
<html> <head> <title>Welcome!</title> </head> <body> <h1>Welcome Beijing!<h1> <p>Hello World!: <a href="abc/helloworld.html">hello world</a> </body> </html>
freemarker使用模板来代替静态的HTML文本。模板文件同样是静态的HTML代码,但是除了这些HTML代码外,代码中还包括了一些freemarker指令元素,指令元素能够做到动态效果。
<html> <head> <title>Welcome!</title> </head> <body> <h1>Welcome ${user}!</h1> <p>Hello World!: <a href="${helloworld.url}">${helloworld.name}</a> </body> </html>
这个模板存放在Web服务器上,看上去像是静态的HTML页面。但不管何时,只要有人来访问这个页面,freemarker将会介入执行,然后动态转换模板,用最新的数据内容替换模板中${...}的部分,生成普通的HTML文本并发送结果到访问者的Web浏览器中去显示。所以访问者的Web浏览器会接收到类似于第一个HTML示例的内容(也就是说,显示普通的HTML文本而没有freemarker的指令),因为浏览器也不会感知到freemarker在服务器被调用了。模板文件本身(存储在Web服务器端的文件)在这个过程中也不会改变什么,所以这个转换过程发生在一次又一次的访问中。这样就保证了显示的信息总是及时的。
概括的讲,模板和数据模型是freemarker所需,并用来生成输出内容的:模板+数据模型=输出
2.数据模型一览
上图中变量扮演目录的角色(根root,animal,mouse,elephant,python,whatnot)被称为hash哈希表。哈希表通过可查找的名称(例如:“animal”,“mouse”,“price”)来访问存储的其他变量(如子变量)。
如果仅存储单值的变量(size,price,text和because)则它们被称为scalars标量。
如果要在模板中使用子变量,那应该从根root开始指定它的路径,每级之间用点来分隔。要访问price和mouse的话,应该从根开始,先是animals,然后是mouse,最后是price,所以应该这样写:animals.mouse.price。当放置${...}这种特定代码在表达式的前后时,我们就告诉freemarker在那个位置上要来输出对应的文本。
sequences序列也是一种非常重要的变量 ,它们和哈希表变量相似,但是它们不存储所包含变量的名称,而是按顺序存储子变量。这样,就可以使用数字索引来访问这些子变量。在这种数据模型中,animal和whatnot。fruits就是序列:
可以使用数组的方括号方式来访问一个序列的子变量。索引从零开始(从零开始是程序员写代码的传统习惯),那么就意味着序列第一项的索引是0,第二项的索引是1,并以此类推。要得到第一个动物名称的话,那么就应该这么写代码:animals[0].name。要得到whatnot.fruits(就是“banana”这个字符串)的第二项,那么就应该这么来写:whatnot.fruits[1]。
标量可以分为如下类别:
字符串:这是文本类型,字符的任意序列,比如“m”,“o”,“u”,“s”,“e”这些,而且name-s和size-s也是字符串范畴。
数字:这是数字值类型,比如price-s这些。在freemarker中字符串“50”和数字50是两种完全不同的类型。前者只是两个字符的序列(这恰好是我们可以读的一个数字),而后者是一个可以在算术运算中直接被使用的数值。
日期/时间:这是时间日期类型。例如动物被捕捉的日期,或商店开始营业的时间。
布尔值:对应对/错(是/否,开/关等)这样仅仅代表正反的值。比如动物可以有一个受保护(protected)的子变量,这个变量存储这个动物是否被保护起来。
总结:
数据模型可以被看做是树状结构的。
标量存储单一的值,这种类型的值可以是字符串,数字,日期/时间或者是布尔值。
哈希表是存储变量和与其相关且有唯一标识名称变量的容器。
序列是存储有序变量的容器。存储的变量可以通过数字索引来检索,索引通常从零开始。