关于FreeMarker
一、 什么是freemarker
FreeMarker是一个“模板引擎” ;一个通用工具生成文本输出(东西向的产品和从HTML源代码)基于模板。 为实现生成HTML网页 ,特别是通过servlet的应用程序后的MVC (模型视图控制器)模式。背后的想法使用MVC模式的动态网页是您单独设计( HTML全文作者)从程序员。每个人都适用于他们所擅长的。 设计人员可以改变的外观网页程序员无需更改或重新编译代码,因为应用程序逻辑( Java程序)和网页设计( FreeMarker模板)隔开。 模板不会成为污染的复杂程序的碎片。
虽然FreeMarker具有一些编程的能力,它不是一个完全成熟的编程语言一样的PHP 。 相反, Java程序编写的数据显示(如SQL查询问题) ,和FreeMarker刚才生成的网页显示文本的编写数据使用的范本。
FreeMarker 不是一个 Web应用框架。 它适用于作为一个组成部分在一个Web应用框架,但FreeMarker引擎本身一无所知HTTP或servlets 。 它只是生成的文本。 因此,它是完全可在非Web应用环境以及。 但是请注意,我们提供了型的解决方案中使用FreeMarker作为视图组件模型2框架(如Struts的) ,这也让您使用的JSP taglibs的模板。 Freemarker 的主要思想是:模板+数据模型=输出。
1.数据模型
数据模型基本上是树.
(root)
|
+- animals
| |
| +- mouse
| | |
| | +- size = "small"
| | |
| | +- price = 50
| |
| +- elephant
| | |
| | +- size = "large"
| | |
| | +- price = 5000
| |
| +- python
| |
| +- size = "medium"
| |
| +- price = 4999
|
+- test = "It is a test"
|
whatnot
|
+- fruits
|
+- (1) = "orange"
|
+- (2) = "banana"
变量存储一个单一的价值( size ,price , name )被称为标 。
目录(root, animals )被称为哈希值
序列 They are similar to hashes, but they don't store names for the variables they contain.是类似的哈希值,Instead, they store the subvariables sequentially, and you can access them with a numerical index.您可以访问它们的数值指标。 For example, in this data-model, and are sequences:例如,在此数据模型whatnot.fruits[1]的序列
摘要:
· The data-model can be visualized as a tree.数据可视化模型可作为一个树。
· Scalars store a single value.标储存单一的价值。 The value can be a string or a number or a date/time or a boolean.此值可以是一个字符串或数字或日期/时间或一个布尔值。
· Hashes are containers that store other variables and associate them with a unique lookup name.哈希的容器存放其他变数并与一个独特的查询名称。
· Sequences are containers that store other variables in an ordered sequence.序列容器存放在其他变数排列顺序。 The stored variables can be retrieved via their numerical index, starting from 0.存储变量可以检索通过其数值指标,从0 。
2.模板
最简单的模板是一个纯HTML文件(或任何文本文件- FreeMarker不仅限于为HTML ) 。 When the client visits that page, FreeMarker will send that HTML to the client as is.当客户端访问该网页, FreeMarker将发送到用户端的HTML一样。 However if you want that page to be more dynamic then you begin to put special parts into the HTML which will be understood by FreeMarker:但是如果你想该网页将更有活力,那么你开始把部分进入特殊的HTML将理解FreeMarker :
· $ ( ... ) : FreeMarker将取代它的产出与实际价值的东西在大括号。 They are called interpolation s.他们被称为插值号………。
· FTL tags (for FreeMarker Template Language tags): FTL tags are a bit similar to HTML tags, but they are instructions to FreeMarker and will not be printed to the output. FTL 标签(用于FreeMarker模板语言标记) :FTL标签有点类似于HTML标记,但它们的指令, FreeMarker并不会被打印输出。 The name of these tags start with . (User-defined FTL tags use instead of , but they are an advanced topic.)这些标记开始# 。 (用户定义的FTL标签用@代替# )
· Comments: Comments are similar to HTML comments, but they are delimited by and . Anything between these delimiters and the delimiter itself will be ignored by FreeMarker, and will not be written to the output. 注释:评论的HTML类似的评论,但他们划定的<#--和--> 。任何这些定界符和分隔本身将被忽略的FreeMarker ,并不会写入输出。
FTL 标签:
· 开始标签: <#directivename parameters>
· 结束标签: </#directivename>
集合标签:
<#list animals as being>
<li>${being.name} for ${being.price} Euros
<#if user == "Big Joe">
(except for you)
</#list> <#-- WRONG! The "if" has to be closed first. -->
</#if>
</ul>
赋值标签:
<#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
字符串输出: ${...}
- Specify values directly
- Retrieving variables
- Top-level variables: user
- Retrieving data from a hash: user.name, user["name"]
- Retrieving data from a sequence: products[5]
- Special variable: .main
- String operations
- Interpolation (or concatenation): "Hello ${user}!" (or "Free" + "Marker")
- Getting a character: name[0]
- Sequence operations
- Concatenation: users + ["guest"]
- Sequence slice: products[10..19] or products[5..]
- Hash operations
- Concatenation: passwords + {"joe":"secret42"}
- Arithmetical calculations: (x * 1.5 + 10) / 2 - y % 100
- Comparison: x == y, x != y, x < y, x > y, x >= y, x <= y, x < y, ...etc.
- Logical operations: !registered && (firstVisit || fromEurope)
- Built-ins: name?upper_case
- Method call: repeat("What", 3)
- Missing value handler operators:
- Default value: name!"unknown" or (user.name)!"unknown" or name! or (user.name)!
- Missing value test: name?? or (user.name)??
二、 怎么用freemarker
1.创建配置实例
首先,必须创建一个freemarker.template.Configuration实例,并调整其设置。 A instance is a central place to store the application level settings of FreeMarker. 配置实例是一个中心位置来存储应用程序级别设置FreeMarker 。 Also, it deals with the creation and caching of pre-parsed templates.此外,它涉及建立和缓存预解析模板。 Probably you will do it only once at the beginning of the application (possibly servlet) life-cycle:也许你会做到这一点只有一次开始的时候,应用程序(可能的servlet )生命周期:
Configuration cfg = new Configuration();
// Specify the data source where the template files come from.
// Here I set a file directory for it:
cfg.setDirectoryForTemplateLoading(new File("模板路径"));
//cfg.setServletContextForTemplateLoading(this.getServletContext(), "模板路径");
//cfg.setClassForTemplateLoading(this.class,” 模板路径”)
// Specify how templates will see the data-model. This is an advanced topic...
// but just use this:
cfg.setObjectWrapper(new DefaultObjectWrapper());
2创建数据模型
在简单的情况下,您可以建立数据模型使用java.lang和java.util定制的Java类和Bean:
· Use for strings.使用构造函数的字符串。
· Use descents for numbers.使用java.lang.Number的数字。
· Use for boolean values.使用java.lang.Boolean的Boolean值。
· Use or Java arrays for sequences.使用java.util.List或Java的arrays。
· Use for hashes.使用java.util.Map的哈希。
· Use your custom bean class for hashes where the items correspond to the bean properties.使用您自定义的bean类哈希的项目相对应的bean属性。 For example the property of can be get as .例如知识产权的产品的价格可以得到作为product.price 。 (The actions of the beans can be exposed as well; see much later here )
(root)
|
+- user = "Big Joe"
|
+- latestProduct
|
+- url = "products/greenmouse.html"
|
+- name = "green mouse"
// Create the root hash
Map root = new HashMap();
// Put string ``user'' into the root
root.put("user", "Big Joe");
// Create the hash for ``latestProduct''
Map latest = new HashMap();
// put ``url'' and ``name'' into latest
latest.put("url", "products/greenmouse.html");
latest.put("name", "green mouse");
// and put it into the root
root.put("latestProduct", latest);
3获取模板
模板是由freemarker.template.Template情况。 Typically you obtain a instance from the instance.通常你获得模板实例从Configuration实例。 Whenever you need a template instance you can get it with its method.当你需要一个模板例如你可以用它getTemplate方法。 Store the example template in the file of the earlier set directory, then you can do this: test.ftl文件早先设定的目录,那么你可以Template temp = cfg.getTemplate("test.ftl");
When you call this, it will create a instance corresponds to , by reading and parsing (compile) it.它会创建一个Template实例对应于test.ftl ,通过阅读 模板路径/test.ftl和解析它。 The instance stores the template in the parsed form, and not as text.Template实例存储的模板中的解析形式,而不是文字。 caches instances, so when you get again, it probably will not create new instance (thus doesn't read and parse the file), just returns the same instance as for the first time.Configuration缓存Template实例,因此当你再次解析test.ftl,它可能不会创建新的Template实例,只需返回同一例如,第一次。
4. 合并模板与数据模型
数据模型+模板=输出,我们有一个数据模型和模板 ,所以获得的产出,我们必须将它们合并。 This is done by the method of the template.
Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
out.flush();
//PrintWriter p = new PrintWriter(new FileOutputStream(new File("1.html")));//如果为servelet则 response.getOutputStream()
// temp.process(root, p); This will print to your terminal the output what you have seen in the first example of the Template Author's Guide. Once you have obtained a instance, you can merge it with different data-models for unlimited times ( instances are basically stateless).
import freemarker.template.*;
import java.util.*;
import java.io.*;
全部代码:
public class Test {
public static void main(String[] args) throws Exception {
/* ------------------------------------------------------------------- */
/* You usually do it only once in the whole application life-cycle: */
/* Create and adjust the configuration */
Configuration cfg = new Configuration();
cfg.setDirectoryForTemplateLoading(
new File("/where/you/store/templates"));
cfg.setObjectWrapper(new DefaultObjectWrapper());
/* ------------------------------------------------------------------- */
/* You usually do these for many times in the application life-cycle: */
/* Get or create a template */
Template temp = cfg.getTemplate("test.ftl");
/* Create a data-model */
Map root = new HashMap();
root.put("user", "Big Joe");
Map latest = new HashMap();
root.put("latestProduct", latest);
latest.put("url", "products/greenmouse.html");
latest.put("name", "green mouse");
/* Merge data-model with template */
Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
out.flush();
}
}
三、 格式化,strust标签,JSTL标签,传值范围.
日期
string(当和一个日期值一起使用)
这个内置标签用指定的格式把日期转换成字符串,(把默认的格式用FreeMarker的ate_format,time_format和datetime_format设置指定对你有好处,那样的话你就不需要这个标签了。
格式可以是一个预定义的,你也可以明确指定格式。
预定义的格式是:short,medium,long和full。定义了结果字符串的长度。例如,如果locale是US_EN,时区是US.PACIFIC,那么:
${openingTime?string.short}
${openingTime?string.medium}
${openingTime?string.long}
${openingTime?string.full}
${nextDiscountDay?string.short}
${nextDiscountDay?string.medium}
${nextDiscountDay?string.long}
${nextDiscountDay?string.full}
${lastUpdated?string.short}
${lastUpdated?string.medium}
${lastUpdated?string.long}
${lastUpdated?string.full}
输出类似这样:
12:45 PM
12:45:09 PM
12:45:09 PM CEST
12:45:09 PM CEST
4/20/07
Apr 20, 2007
April 20, 2007
Friday, April 20, 2007
4/20/07 12:45 PM
Apr 20, 2007 12:45:09 PM
April 20, 2007 12:45:09 PM CEST
Friday, April 20, 2007 12:45:09 PM CEST
short,medium.long和full准确的意思依赖于当前locale(语言),此外,这是你运行FreeMarker的java实现平台所指定的,而不是FreeMarker。
对于即包含日期和时间的日期值,你可以单独的指定日期和时间部分的长度。
${lastUpdated?string.short_long} <#-- short date, long time -->
${lastUpdated?string.medium_short} <#-- medium date, short time -->
将会输出:
4/8/03 9:24:44 PM PDT
Apr 8, 2003 9:24 PM
注意:string.short跟?string.short_short是一样的,?string.medium和string.medium_medium一样……
警告:
不幸的是,由于java平台的限制。当你在Data Model中存有日期值的时候,FreeMarker不能决定该变量只存储日期部分或者时间部分再或者日期和时间。这种情况下当你像${lastUpdated?string.short}或者简单的${lastUpdated}这样写的时候,FreeMarker不知道如何显示日期。这样它会停下来,并且报错。为了防止这样,你可以使用?date,?time和?datetime内置标签来帮助FreeMarker。举例:${lastUpdated?datetime?string.short}.询问程序员某个日期变量是否存在这个问题,或者一直使用?date,?time和?datetime。
你可以使用?string(格式)明确指定格式,代替预定义格式。格式使用java日期格式语法例如:
${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}
${lastUpdated?string("EEE, MMM d, ''yy")}
${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}
将会输出:
2003-04-08 21:24:44 Pacific Daylight Time
Tue, Apr 8, '03
Tuesday, April 08, 2003, 09:24:44 PM (PDT)
注意:
不像预定义格式,你不需要在指定的格式上使用?date,?time和?datetime,因为你指定的格式告诉FreeMarKer显示日期的哪部分。无论如何,FreeMarker都会相信你,so you can show "noise" if you display parts that are actually not stored in the variable.例如:${openingTime?string("yyyy-mm-dd hh:mm:ss a")},openingTime只存储了时间。将会显示1790-01-01 09:24:44 PM.
格式也可以是short,medium……"short_medium"等等。这样跟你用"."使用预定义的格式是一样的:someDate?string("short")和someDate?string.short是相当的。
date,time,datetime
这些标签可以用来指定日期变量中的哪些部分被使用。
date:只使用年、月、日
time:只使用时、分、秒和毫秒部分
datetime:日期和时间两部分都被使用
理想情况下,你不需要使用它们。不幸的是,由于java平台的技术限制。FreeMarker有的时候不能找到日期变量使用的部分(例如:只有年月日,或者只有时分秒,或者两者)询问程序员那个变量存在这个问题。如果FreeMarker需要执行一个需要这个变量的操作--就像把日期作为字符显示--但是它不知道使用那些部分,它会停下来报错。这就是你必须使用这些标签的情况。例如:假定openingTime就是这样一个问题变量:
<#assign x = openingTime> <#-- no problem can occur here -->
${openingTime?time} <#-- without ?time it would fail -->
<#-- For the sake of better understanding, consider this: -->
<#assign openingTime = openingTime?time>
${openingTime} <#-- this will work now -->
另一种用法:切短日期。例如:
Last updated: ${lastUpdated} <#-- assume that lastUpdated is a date-time value -->
Last updated date: ${lastUpdated?date}
Last updated time: ${lastUpdated?time}
将显示:
Last updated: 04/25/2003 08:00:54 PM
Last updated date: 04/25/2003
Last updated time: 08:00:54 PM
数字
把一个数字转换成字符串时,使用的java语言使用的数字格式(跟Locale相关),这样是为了符合人类的习惯.比如300000会显示成300,000.如果我们把这个数字作为表单的一个域值放进数据库或者在javascript中使用时,需要再转换成适合计算机输入的格式.这个标签用来输出数字(例如用${x?c}替换${x})防止这种格式转换.
string(当跟一个数字一起使用时)
将一个数字转换成字符传,使用默认的格式,当然也可以明确的要使用的指定数字或者日期格式.
有3中预置格式:number,currency,percent.你可以像下面一样使用表达式:
|
|
| |
|
|
|
如果使用的是的US 英语,输出是
|
|
输出前3个是一样的,因为前2个使用默认的格式,在这里是"number".你可以改变默认设置
|
|
| |
|
|
| |
|
|
|
将会输出:
|
|
| |
|
|
|
除了3种预置的格式,你还可以使用java小数格式化语法,即可以像预置格式一样使用,也可以像明确的格式选择器:
|
|
| |
|
|
| |
|
|
|
输出:
|
|
| |
|
|
| |
|
|
|
注意:你也可以${answer?string("number")},跟${answer?string.number}.是一样的。
注意:数字格式是LOCALE敏感的:
|
|
| |
|
|
| |
|
|
|
输出:
|
|
| |
|
|
|
3标签
<#assign html=JspTaglibs["/WEB-INF/struts-html.tld"]>
<#assign bean= JspTaglibs["/WEB-INF/struts-bean.tld"]>
<#assign logic=JspTaglibs["/WEB-INF/struts-logic.tld"]>
<#assign c= JspTaglibs["/WEB-INF/c.tld"]>
. <@logic.iterate name="m" id="x" indexId="index">
<@bean.write name="x" property="userName"/>
4作用域
${Request.user.userName}
${Session.user}
四、 其他
Freemarker API 地址:http://freemarker.sourceforge.net/docs/api/index.html
Freemarker 使用手册地址:http://freemarker.sourceforge.net/docs/index.html