freemarker_freemarker教程 - CSDN
freemarker 订阅
FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。FreeMarker是免费的,基于Apache许可证2.0版本发布。其模板编写为FreeMarker Template Language(FTL),属于简单、专用的语言。需要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,主要用于如何展现数据, 而在模板之外注意于要展示什么数据 [1]  。 展开全文
FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。FreeMarker是免费的,基于Apache许可证2.0版本发布。其模板编写为FreeMarker Template Language(FTL),属于简单、专用的语言。需要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,主要用于如何展现数据, 而在模板之外注意于要展示什么数据 [1]  。
信息
最新版本
FreeMarker 2.3.23
类    别
模板引擎
特    点
通用性高,模板语言强大
中文名
福瑞马克
外文名
FreeMarker
freemarker发展历史
FreeMarker最初的设计,是被用来在MVC模式的Web开发框架中生成HTML页面的,没有被绑定到Servlet或HTML或任意Web相关的东西上,它也可以用于非Web应用环境中。1999年末,FreeMarker的第一个版本出现在SourceForge网站上,它最初是由Benjamin Geer和Mike Bayer编写,他们定义了FreeMarker最基本的语法。FreeMarker 1获得了LGPL(宽通用公共许可证)的许可,其版权归属于Benjamin Geer。此外,Nicholas Cull、Holger Arendt等人对该项目也做出了主要贡献。在2002年初,Jonathan Revusky用JavaCC重写了FreeMarker的核心代码(语法和编译),虽然对FreeMarker 1尽量做到向后兼容,但几乎是完全重写了。Attila Szegedi对FreeMarker 2也有重要影响,除了重构和优化一些核心的API(应用程序编程接口),Attila还作为主要编写者实现了FreeMarker对日期、时间的支持,写出的freemarker.ext*包完成对javabean、Jython和XML的映射,以及HTTP servlet、JSP和Ant的集成。Dániel Dékány主要负责文档以及项目的维护(截至2011年,Dániel Dékány仍是该项目的主要维护者) [2]  。2002年3月18日,FreeMarker的第一个发布候选版2.0 RC1发布 [3]  ,又经过了2个候选版的BUG修复之后,正式版的Free Marker2.0于2002年4月18日发布 [4]  。2002年10月17日,FreeMarker 2.1 发布,该版本并不能与2.0版本兼容,所以使用者如果不是新建工程的话,需要重新审视已有的代码和模版 [5]  。由于项目没有法律实体,FreeMarker的2.0.x和2.1.x的版权仍归属Benjamin Geer。而在2002年12月制作2.2版本时,Benjamin Geer出于对自由开源许可的理解,将代码库版权转给Visigoth Software Society(西班牙的一个非营利性软件协会)和共同创办人Jonathan Revusky [2]  。2003年3月27日,FreeMarker 2.2 发布,这个版本引入了一些非常重要的新特性,但是有一些功能却不能逆向兼容 [6]  。在2.2的版本中,可能最重要的新特性就是namespace支持,这使得FreeMarker成为了合适大规模项目的工具,因为它允许不同页面分享的宏和变量没有任何名称空间冲突。同时,宏也变得更加强大,因为他们可以调用可选目标,并且宏现作为一流的变量,可以传递给其他宏使用。此外2.2中另一个吸引人的特性为,FreeMarker可以利用由第三方所写的JSP标记库 [7]  。在此之后,2.3版本之前,共更新了8个版本 [6]  。2004年6月15日,FreeMarker 2.3 发布,此版本对2.2系列进行了质量上的改进,以及引入了大量的新功能。最主要的改进点在于可以定义函数(方法)模版,插入字符串变量,支持宏参数和更为智能的默认对象包装。但2.3并不支持2.2.x的向后兼容,所以仅供新项目使用 [8]  。2005年1月4日的2.3.1版本到10月10日2.3.4版本主要是编写和维护一些新特性,以及BUG错误修复。2006年3月11日发布的2.3.5版本,因为发现严重错误而被撤回 [9]  ,在后续的2.3.6版本中修复。2.3.7时出了一个测试版本用于BUG修正和FreemarkerServlet的改进,其正式版中新增substring用于处理空的或缺失的变量 [10]  。 2006年7月9日发布2.3.8版本,提高了对JSP 2.0的兼容性 [11]  。2007年1月23日发布2.3.9版本,包含了对JDK 1.5枚举和通过BeansWrapper公共类字段的支持 [12]  。2007年4月20的2.3.10版本到2009年12月10日的2.3.16版本都是一些小性能改进和BUG修复。2011年5月17日,FreeMarker 2.3.17 发布,该版本主要进行了安全性的修复并扩充了一些内建函数 [13]  。2011年5月22日,FreeMarker 2.3.18 发布,修复jar包相关的bug [14]  。2012年2月29日,FreeMarker 2.3.19 发布,该版本修复了两个重要的bug,另外新增对JSON字符串进行处理的方法json_string等小改动 [15]  。2013年6月27日,FreeMarker 2.3.20 发布,主要对于使用IDE工具的修改 [16]  。2014年10月12日,FreeMarker 2.3.21 发布,对Java版本的最低要求从1.2变为1.4。由于旧的BSD风格许可不被OSI所承认,且Visigoth Software Society停滞不前,其许可变更为Apache 2.0版,所有者转为Attila Szegedi、Daniel Dekany和Jonathan Revusky(FreeMarker 2的主要开发者) [2]  。2015年3月1日,FreeMarker 2.3.22 发布,在FTL模板和Java方面做了一些更改 [17]  。2015年7月1日,FreeMarker经过投票进入了Apache Incubator,其项目授予给Apache软件基金会 [2]  。2015年7月5日,FreeMarker 2.3.23 发布,在FTL模板和Java上做了大量修改。尤其增加了list中items和else的字指令,使常见遍历任务更简单 [18]  。2015年9月2日,FreeMarker的主代码库从GitHub导入到Apache软件基金会的基础设施中发展 [2]  。2018年3月21日,FreeMarker在Apache Incubator中升级为顶级项目 [2]  。
收起全文
精华内容
参与话题
  • 一篇很全面的freemarker教程

    万次阅读 多人点赞 2012-08-24 00:24:55
    FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1,文本:直接输出的部分 2,注释:格式部分,不会输出 3,插值:即${...}或#{...}格式的部分,将使用数据模型中的部分替代...
    copy自http://demojava.iteye.com/blog/800204

    以下内容全部是网上收集:

    FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成:
    1,文本:直接输出的部分
    2,注释:<#-- ... -->格式部分,不会输出
    3,插值:即${...}或#{...}格式的部分,将使用数据模型中的部分替代输出
    4,FTL指令:FreeMarker指定,和HTML标记类似,名字前加#予以区分,不会输出

    下面是一个FreeMarker模板的例子,包含了以上所说的4个部分
    <html><br>
    <head><br>
    <title>Welcome!</title><br>
    </head><br>
    <body><br>
    <#-- 注释部分 --><br>
    <#-- 下面使用插值 -->
    <h1>Welcome ${user} !</h1><br>
    <p>We have these animals:<br>
    <u1><br>
    <#-- 使用FTL指令 -->
    <#list animals as being><br>
       <li>${being.name} for ${being.price} Euros<br>
    <#list><br>
    <u1><br>
    </body><br>
    </html>

    1, FTL指令规则

    在FreeMarker中,使用FTL标签来使用指令,FreeMarker有3种FTL标签,这和HTML标签是完全类似的.
    1,开始标签:<#directivename parameter>
    2,结束标签:</#directivename>
    3,空标签:<#directivename parameter/>

    实际上,使用标签时前面的符号#也可能变成@,如果该指令是一个用户指令而不是系统内建指令时,应将#符号改成@符号.
    使用FTL标签时, 应该有正确的嵌套,而不是交叉使用,这和XML标签的用法完全一样.如果全用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息.FreeMarker会忽略FTL标签中的空白字符.值得注意的是< , /> 和指令之间不允许有空白字符.

    2, 插值规则

    FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式化插值:#{expr}或#{expr;format}

    2.1 通用插值

    对于通用插值,又可以分为以下4种情况:
    1,插值结果为字符串值:直接输出表达式结果
    2,插值结果为数字值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:
    <#settion number_format="currency"/>
    <#assign answer=42/>
    ${answer}
    ${answer?string} <#-- the same as ${answer} -->
    ${answer?string.number}
    ${answer?string.currency}
    ${answer?string.percent}
    ${answer}
    输出结果是:
    $42.00
    $42.00
    42
    $42.00
    4,200%
    3,插值结果为日期值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:
    ${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')'")}
    输出结果是:
    2008-04-08 08:08:08 Pacific Daylight Time
    Tue, Apr 8, '03
    Tuesday, April 08, 2003, 08:08:08 PM (PDT)
    4,插值结果为布尔值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:
    <#assign foo=true/>
    ${foo?string("yes", "no")}
    输出结果是:
    yes

    2.2 数字格式化插值

    数字格式化插值可采用#{expr;format}形式来格式化数字,其中format可以是:
    mX:小数部分最小X位
    MX:小数部分最大X位
    如下面的例子:
    <#assign x=2.582/>
    <#assign y=4/>
    #{x; M2} <#-- 输出2.58 -->
    #{y; M2} <#-- 输出4 -->
    #{x; m2} <#-- 输出2.6 -->
    #{y; m2} <#-- 输出4.0 -->
    #{x; m1M2} <#-- 输出2.58 -->
    #{x; m1M2} <#-- 输出4.0 -->

    3, 表达式

    表达式是FreeMarker模板的核心功能,表达式放置在插值语法${}之中时,表明需要输出表达式的值;表达式语法也可与FreeMarker 标签结合,用于控制输出.实际上FreeMarker的表达式功能非常强大,它不仅支持直接指定值,输出变量值,也支持字符串格式化输出和集合访问等功能.

    3.1 直接指定值

    使用直接指定值语法让FreeMarker直接输出插值中的值,而不是输出变量值.直接指定值可以是字符串,数值,布尔值,集合和MAP对象.

    1,字符串
    直接指定字符串值使用单引号或双引号限定,如果字符串值中包含特殊字符需要转义,看下面的例子:
    ${"我的文件保存在C:\\盘"}
    ${'我名字是\"annlee\"'}
    输出结果是:
    我的文件保存在C:\盘
    我名字是"annlee"

    FreeMarker支持如下转义字符:
    \";双引号(u0022)
    \';单引号(u0027)
    \\;反斜杠(u005C)
    \n;换行(u000A)
    \r;回车(u000D)
    \t;Tab(u0009)
    \b;退格键(u0008)
    \f;Form feed(u000C)
    \l;<
    \g;>
    \a;&
    \{;{
    \xCode;直接通过4位的16进制数来指定Unicode码,输出该unicode码对应的字符.

    如果某段文本中包含大量的特殊符号,FreeMarker提供了另一种特殊格式:可以在指定字符串内容的引号前增加r标记,在r标记后的文件将会直接输出.看如下代码:
    ${r"${foo}"}
    ${r"C:\foo\bar"}
    输出结果是:
    ${foo}
    C:\foo\bar

    2,数值
    表达式中的数值直接输出,不需要引号.小数点使用"."分隔,不能使用分组","符号.FreeMarker目前还不支持科学计数法,所以"1E3"是错误的.在FreeMarker表达式中使用数值需要注意以下几点:
    1,数值不能省略小数点前面的0,所以".5"是错误的写法
    2,数值8 , +8 , 8.00都是相同的

    3,布尔值
    直接使用true和false,不使用引号.

    4,集合
    集合以方括号包括,各集合元素之间以英文逗号","分隔,看如下的例子:
    <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x>
    ${x}
    </#list>
    输出结果是:
    星期一
    星期二
    星期三
    星期四
    星期五
    星期六
    星期天

    除此之外,集合元素也可以是表达式,例子如下:
    [2 + 2, [1, 2, 3, 4], "whatnot"]

    还可以使用数字范围定义数字集合,如2..5等同于[2, 3, 4, 5],但是更有效率.注意,使用数字范围来定义集合时无需使用方括号,数字范围也支持反递增的数字范围,如5..2

    5,Map对象
    Map对象使用花括号包括,Map中的key-value对之间以英文冒号":"分隔,多组key-value对之间以英文逗号","分隔.下面是一个例子:
    {"语文":78, "数学":80}
    Map对象的key和value都是表达式,但是key必须是字符串

    3.2 输出变量值

    FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象中的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性.下面分别讨论这些情况

    1,顶层变量
    所谓顶层变量就是直接放在数据模型中的值,例如有如下数据模型:
    Map root = new HashMap();   //创建数据模型
    root.put("name","annlee");   //name是一个顶层变量

    对于顶层变量,直接使用${variableName}来输出变量值,变量名只能是字母,数字,下划线,$,@和#的组合,且不能以数字开头号.为了输出上面的name的值,可以使用如下语法:
    ${name}

    2,输出集合元素
    如果需要输出集合元素,则可以根据集合元素的索引来输出集合元素,集合元素的索引以方括号指定.假设有索引:
    ["星期一","星期二","星期三","星期四","星期五","星期六","星期天"].该索引名为week,如果需要输出星期三,则可以使用如下语法:
    ${week[2]}   //输出第三个集合元素

    此外,FreeMarker还支持返回集合的子集合,如果需要返回集合的子集合,则可以使用如下语法:
    week[3..5]   //返回week集合的子集合,子集合中的元素是week集合中的第4-6个元素

    3,输出Map元素
    这里的Map对象可以是直接HashMap的实例,甚至包括JavaBean实例,对于JavaBean实例而言,我们一样可以把其当成属性为key,属性值为value的Map实例.为了输出Map元素的值,可以使用点语法或方括号语法.假如有下面的数据模型:
    Map root = new HashMap();
    Book book = new Book();
    Author author = new Author();
    author.setName("annlee");
    author.setAddress("gz");
    book.setName("struts2");
    book.setAuthor(author);
    root.put("info","struts");
    root.put("book", book);

    为了访问数据模型中名为struts2的书的作者的名字,可以使用如下语法:
    book.author.name    //全部使用点语法
    book["author"].name
    book.author["name"]    //混合使用点语法和方括号语法
    book["author"]["name"]   //全部使用方括号语法

    使用点语法时,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字可以是任意表达式的结果.

    3.3, 字符串操作

    FreeMarker的表达式对字符串操作非常灵活,可以将字符串常量和变量连接起来,也可以返回字符串的子串等.

    字符串连接有两种语法:
    1,使用${..}或#{..}在字符串常量部分插入表达式的值,从而完成字符串连接.
    2,直接使用连接运算符+来连接字符串

    例如有如下数据模型:
    Map root = new HashMap(); root.put("user","annlee");
    下面将user变量和常量连接起来:
    ${"hello, ${user}!"}   //使用第一种语法来连接
    ${"hello, " + user + "!"} //使用+号来连接
    上面的输出字符串都是hello,annlee!,可以看出这两种语法的效果完全一样.

    值得注意的是,${..}只能用于文本部分,不能用于表达式,下面的代码是错误的:
    <#if ${isBig}>Wow!</#if>
    <#if "${isBig}">Wow!</#if>
    应该写成:<#if isBig>Wow!</#if>

    截取子串可以根据字符串的索引来进行,截取子串时如果只指定了一个索引值,则用于取得字符串中指定索引所对应的字符;如果指定两个索引值,则返回两个索引中间的字符串子串.假如有如下数据模型:
    Map root = new HashMap(); root.put("book","struts2,freemarker");
    可以通过如下语法来截取子串:
    ${book[0]}${book[4]}   //结果是su
    ${book[1..4]}     //结果是tru

    3.4 集合连接运算符

    这里所说的集合运算符是将两个集合连接成一个新的集合,连接集合的运算符是+,看如下的例子:
    <#list ["星期一","星期二","星期三"] + ["星期四","星期五","星期六","星期天"] as x>
    ${x}
    </#list>
    输出结果是:星期一 星期二 星期三 星期四 星期五 星期六 星期天

    3.5 Map连接运算符

    Map对象的连接运算符也是将两个Map对象连接成一个新的Map对象,Map对象的连接运算符是+,如果两个Map对象具有相同的key,则右边的值替代左边的值.看如下的例子:
    <#assign scores = {"语文":86,"数学":78} + {"数学":87,"Java":93}>
    语文成绩是${scores.语文}
    数学成绩是${scores.数学}
    Java成绩是${scores.Java}
    输出结果是:
    语文成绩是86
    数学成绩是87
    Java成绩是93

    3.6 算术运算符

    FreeMarker表达式中完全支持算术运算,FreeMarker支持的算术运算符包括:+, - , * , / , % 看如下的代码:
    <#assign x=5>
    ${ x * x - 100 }
    ${ x /2 }
    ${ 12 %10 }
    输出结果是:
    -75   2.5   2

    在表达式中使用算术运算符时要注意以下几点:
    1,运算符两边的运算数字必须是数字
    2,使用+运算符时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串再连接,如:${3 + "5"},结果是:35

    使用内建的int函数可对数值取整,如:
    <#assign x=5>
    ${ (x/2)?int }
    ${ 1.1?int }
    ${ 1.999?int }
    ${ -1.1?int }
    ${ -1.999?int }
    结果是:2 1 1 -1 -1

    3.7 比较运算符

    表达式中支持的比较运算符有如下几个:
    1,=或者==:判断两个值是否相等.
    2,!=:判断两个值是否不等.
    3,>或者gt:判断左边值是否大于右边值
    4,>=或者gte:判断左边值是否大于等于右边值
    5,<或者lt:判断左边值是否小于右边值
    6,<=或者lte:判断左边值是否小于等于右边值

    注意:=和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且FreeMarker是精确比较,"x","x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为 FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况,如:<#if (x>y)>

    3.8 逻辑运算符

    逻辑运算符有如下几个:
    逻辑与:&&
    逻辑或:||
    逻辑非:!
    逻辑运算符只能作用于布尔值,否则将产生错误

    3.9 内建函数

    FreeMarker还提供了一些内建函数来转换输出,可以在任何变量后紧跟?,?后紧跟内建函数,就可以通过内建函数来轮换输出变量.下面是常用的内建的字符串函数:
    html:对字符串进行HTML编码
    cap_first:使字符串第一个字母大写
    lower_case:将字符串转换成小写
    upper_case:将字符串转换成大写
    trim:去掉字符串前后的空白字符

    下面是集合的常用内建函数
    size:获取序列中元素的个数

    下面是数字值的常用内建函数
    int:取得数字的整数部分,结果带符号

    例如:
    <#assign test="Tom & Jerry">
    ${test?html}
    ${test?upper_case?html}
    结果是:Tom &amp; Jerry   TOM &amp; JERRY

    3.10 空值处理运算符

    FreeMarker对空值的处理非常严格,FreeMarker的变量必须有值,没有被赋值的变量就会抛出异常,因为FreeMarker未赋值的变量强制出错可以杜绝很多潜在的错误,如缺失潜在的变量命名,或者其他变量错误.这里所说的空值,实际上也包括那些并不存在的变量,对于一个Java的 null值而言,我们认为这个变量是存在的,只是它的值为null,但对于FreeMarker模板而言,它无法理解null值,null值和不存在的变量完全相同.

    为了处理缺失变量,FreeMarker提供了两个运算符:
    !:指定缺失变量的默认值
    ??:判断某个变量是否存在

    其中,!运算符的用法有如下两种:
    variable!或variable!defaultValue,第一种用法不给缺失的变量指定默认值,表明默认值是空字符串,长度为0的集合,或者长度为0的Map对象.

    使用!指定默认值时,并不要求默认值的类型和变量类型相同.使用??运算符非常简单,它总是返回一个布尔值,用法为:variable??,如果该变量存在,返回true,否则返回false

    3.11 运算符的优先级

    FreeMarker中的运算符优先级如下(由高到低排列):
    1,一元运算符:!
    2,内建函数:?
    3,乘除法:*, / , %
    4,加减法:- , +
    5,比较:> , < , >= , <= (lt , lte , gt , gte)
    6,相等:== , = , !=
    7,逻辑与:&&
    8,逻辑或:||
    9,数字范围:..

    实际上,我们在开发过程中应该使用括号来严格区分,这样的可读性好,出错少

    4 FreeMarker的常用指令

    FreeMarker的FTL指令也是模板的重要组成部分,这些指令可实现对数据模型所包含数据的抚今迭代,分支控制.除此之外,还有一些重要的功能,也是通过FTL指令来实现的.

    4.1 if指令

    这是一个典型的分支控制指令,该指令的作用完全类似于Java语言中的if,if指令的语法格式如下:
    <#if condition>...
    <#elseif condition>...
    <#elseif condition>...
    <#else> ...
    </#if>

    例子如下:
    <#assign age=23>
    <#if (age>60)>老年人
    <#elseif (age>40)>中年人
    <#elseif (age>20)>青年人
    <#else> 少年人
    </#if>
    输出结果是:青年人
    上面的代码中的逻辑表达式用括号括起来主要是因为里面有>符号,由于FreeMarker会将>符号当成标签的结束字符,可能导致程序出错,为了避免这种情况,我们应该在凡是出现这些符号的地方都使用括号.

    4.2 switch , case , default , break指令

    这些指令显然是分支指令,作用类似于Java的switch语句,switch指令的语法结构如下:
    <#switch value>
    <#case refValue>...<#break>
    <#case refValue>...<#break>
    <#default>...
    </#switch>

    4.3 list, break指令

    list指令是一个迭代输出指令,用于迭代输出数据模型中的集合,list指令的语法格式如下:
    <#list sequence as item>
    ...
    </#list>
    上面的语法格式中,sequence就是一个集合对象,也可以是一个表达式,但该表达式将返回一个集合对象,而item是一个任意的名字,就是被迭代输出的集合元素.此外,迭代集合对象时,还包含两个特殊的循环变量:
    item_index:当前变量的索引值
    item_has_next:是否存在下一个对象
    也可以使用<#break>指令跳出迭代

    例子如下:
    <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x>
    ${x_index + 1}.${x}<#if x_has_next>,</if>
    <#if x="星期四"><#break></#if>
    </#list>

    4.4 include指令

    include指令的作用类似于JSP的包含指令,用于包含指定页.include指令的语法格式如下:
    <#include filename [options]>
    在上面的语法格式中,两个参数的解释如下:
    filename:该参数指定被包含的模板文件
    options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,其中encoding指定包含页面时所用的解码集,而parse指定被包含文件是否作为FTL文件来解析,如果省略了parse选项值,则该选项默认是true.

    4.5 import指令

    该指令用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中,import指令的语法格式如下:
    <#import "/lib/common.ftl" as com>
    上面的代码将导入/lib/common.ftl模板文件中的所有变量,交将这些变量放置在一个名为com的Map对象中.

    4.6 noparse指令

    noparse指令指定FreeMarker不处理该指定里包含的内容,该指令的语法格式如下:
    <#noparse>...</#noparse>

    看如下的例子:
    <#noparse>
    <#list books as book>
       <tr><td>${book.name}<td>作者:${book.author}
    </#list>
    </#noparse>
    输出如下:
    <#list books as book>
       <tr><td>${book.name}<td>作者:${book.author}
    </#list>

    4.7 escape , noescape指令

    escape指令导致body区的插值都会被自动加上escape表达式,但不会影响字符串内的插值,只会影响到body内出现的插值,使用escape指令的语法格式如下:
    <#escape identifier as expression>...
    <#noescape>...</#noescape>
    </#escape>

    看如下的代码:
    <#escape x as x?html>
    First name:${firstName}
    Last name:${lastName}
    Maiden name:${maidenName}
    </#escape>
    上面的代码等同于:
    First name:${firstName?html}
    Last name:${lastName?html}
    Maiden name:${maidenName?html}

    escape指令在解析模板时起作用而不是在运行时起作用,除此之外,escape指令也嵌套使用,子escape继承父escape的规则,如下例子:
    <#escape x as x?html>
    Customer Name:${customerName}
    Items to ship;
    <#escape x as itemCodeToNameMap[x]>
       ${itemCode1}
       ${itemCode2}
       ${itemCode3}
       ${itemCode4}
    </#escape>
    </#escape>
    上面的代码类似于:
    Customer Name:${customerName?html}
    Items to ship;
    ${itemCodeToNameMap[itemCode1]?html}
    ${itemCodeToNameMap[itemCode2]?html}
    ${itemCodeToNameMap[itemCode3]?html}
    ${itemCodeToNameMap[itemCode4]?html}

    对于放在escape指令中所有的插值而言,这此插值将被自动加上escape表达式,如果需要指定escape指令中某些插值无需添加escape表达式,则应该使用noescape指令,放在noescape指令中的插值将不会添加escape表达式.

    4.8 assign指令

    assign指令在前面已经使用了多次,它用于为该模板页面创建或替换一个顶层变量,assign指令的用法有多种,包含创建或替换一个顶层变量, 或者创建或替换多个变量等,它的最简单的语法如下:<#assign name=value [in namespacehash]>,这个用法用于指定一个名为name的变量,该变量的值为value,此外,FreeMarker允许在使用 assign指令里增加in子句,in子句用于将创建的name变量放入namespacehash命名空间中.

    assign指令还有如下用法:<#assign name1=value1 name2=value2 ... nameN=valueN [in namespacehash]>,这个语法可以同时创建或替换多个顶层变量,此外,还有一种复杂的用法,如果需要创建或替换的变量值是一个复杂的表达式,则可以使用如下语法格式:<#assign name [in namespacehash]>capture this</#assign>,在这个语法中,是指将assign指令的内容赋值给name变量.如下例子:
    <#assign x>
    <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n>
    ${n}
    </#list>
    </#assign>
    ${x}
    上面的代码将产生如下输出:星期一 星期二 星期三 星期四 星期五 星期六 星期天

    虽然assign指定了这种复杂变量值的用法,但是我们也不要滥用这种用法,如下例子:<#assign x>Hello ${user}!</#assign>,以上代码改为如下写法更合适:<#assign x="Hello ${user}!">

    4.9 setting指令

    该指令用于设置FreeMarker的运行环境,该指令的语法格式如下:<#setting name=value>,在这个格式中,name的取值范围包含如下几个:
    locale:该选项指定该模板所用的国家/语言选项
    number_format:指定格式化输出数字的格式
    boolean_format:指定两个布尔值的语法格式,默认值是true,false
    date_format,time_format,datetime_format:指定格式化输出日期的格式
    time_zone:设置格式化输出日期时所使用的时区

    4.10 macro , nested , return指令

    macro可以用于实现自定义指令,通过使用自定义指令,可以将一段模板片段定义成一个用户指令,使用macro指令的语法格式如下:
    <#macro name param1 param2 ... paramN>
    ...
    <#nested loopvar1, loopvar2, ..., loopvarN>
    ...
    <#return>
    ...
    </#macro>
    在上面的格式片段中,包含了如下几个部分:
    name:name属性指定的是该自定义指令的名字,使用自定义指令时可以传入多个参数
    paramX:该属性就是指定使用自定义指令时报参数,使用该自定义指令时,必须为这些参数传入值
    nested指令:nested标签输出使用自定义指令时的中间部分
    nested指令中的循环变量:这此循环变量将由macro定义部分指定,传给使用标签的模板
    return指令:该指令可用于随时结束该自定义指令.

    看如下的例子:
    <#macro book>   //定义一个自定义指令
    j2ee
    </#macro>
    <@book />    //使用刚才定义的指令
    上面的代码输出结果为:j2ee

    在上面的代码中,可能很难看出自定义标签的用处,因为我们定义的book指令所包含的内容非常简单,实际上,自定义标签可包含非常多的内容,从而可以实现更好的代码复用.此外,还可以在定义自定义指令时,为自定义指令指定参数,看如下代码:
    <#macro book booklist>     //定义一个自定义指令booklist是参数
    <#list booklist as book>
       ${book}
    </#list>
    </#macro>
    <@book booklist=["spring","j2ee"] />   //使用刚刚定义的指令
    上面的代码为book指令传入了一个参数值,上面的代码的输出结果为:spring j2ee

    不仅如此,还可以在自定义指令时使用nested指令来输出自定义指令的中间部分,看如下例子:
    <#macro page title>
    <html>
    <head>
       <title>FreeMarker示例页面 - ${title?html}</title>
    </head>
    <body>
       <h1>${title?html}</h1>
       <#nested>      //用于引入用户自定义指令的标签体
    </body>
    </html>
    </#macro>
    上面的代码将一个HTML页面模板定义成一个page指令,则可以在其他页面中如此page指令:
    <#import "/common.ftl" as com>     //假设上面的模板页面名为common.ftl,导入页面
    <@com.page title="book list">
    <u1>
    <li>spring</li>
    <li>j2ee</li>
    </ul>
    </@com.page>

    从上面的例子可以看出,使用macro和nested指令可以非常容易地实现页面装饰效果,此外,还可以在使用nested指令时,指定一个或多个循环变量,看如下代码:
    <#macro book>
    <#nested 1>      //使用book指令时指定了一个循环变量值
    <#nested 2>
    </#macro>
    <@book ;x> ${x} .图书</@book>
    当使用nested指令传入变量值时,在使用该自定义指令时,就需要使用一个占位符(如book指令后的;x).上面的代码输出文本如下:
    1 .图书    2 .图书

    在nested指令中使用循环变量时,可以使用多个循环变量,看如下代码:
    <#macro repeat count>
    <#list 1..count as x>     //使用nested指令时指定了三个循环变量
       <#nested x, x/2, x==count>
    </#list>
    </#macro>
    <@repeat count=4 ; c halfc last>
    ${c}. ${halfc}<#if last> Last! </#if>
    </@repeat>
    上面的输出结果为:
    1. 0.5   2. 1   3. 1.5   4. 2 Last;

    return指令用于结束macro指令,一旦在macro指令中执行了return指令,则FreeMarker不会继续处理macro指令里的内容,看如下代码:
    <#macro book>
    spring
    <#return>
    j2ee
    </#macro>
    <@book />
    上面的代码输出:spring,而j2ee位于return指令之后,不会输出.

    if, else, elseif
    switch, case, default, break
    list, break
    include
    Import
    compress
    escape, noescape
    assign
    global
    setting
    macro, nested, return
    t, lt, rt
    3一些常用方法或注意事项
    表达式转换类
    数字循环
    对浮点取整数
    给变量默认值
    判断对象是不是null
    常用格式化日期
    添加全局共享变量数据模型
    直接调用java对象的方法
    字符串处理(内置方法)
    在模板里对sequences和hashes初始化
    注释标志
    sequences内置方法
    hashes内置方法
    4 freemarker在web开发中注意事项
    web中常用的几个对象
    view中值的搜索顺序
    在模板里ftl里使用标签
    如何初始化共享变量
    与webwork整合配置
    5高级方法
    自定义方法
    自定义 Transforms

                                    
    1概念
    最常用的3个概念
    sequence  序列,对应java里的list、数组等非键值对的集合
    hash      键值对的集合
    namespace 对一个ftl文件的引用,利用这个名字可以访问到该ftl文件的资源

    2指令
    if, else, elseif
    语法
    <#if condition>
      ...
    <#elseif condition2>
      ...
    <#elseif condition3>
      ...
    ...
    <#else>
      ...
    </#if>
    用例
    <#if x = 1>
      x is 1
    </#if>

    <#if x = 1>
      x is 1
    <#else>
      x is not 1
    </#if>

    switch, case, default, break
    语法
    <#switch value>
      <#case refValue1>
        ...
        <#break>
      <#case refValue2>
        ...
        <#break>
      ...
      <#case refValueN>
        ...
        <#break>
      <#default>
        ...
    </#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>
    数字
    <#switch x>
      <#case x = 1>
        1
      <#case x = 2>
        2
      <#default>
        d
    </#switch>

    如果x=1 输出 1 2, x=2输出 2, x=3 输出d

    list, break
    语法
    <#list sequence as item>
    ...
    <#if item = "spring"><#break></#if>
    ...
    </#list>
    关键字
    item_index:是list当前值的下标
    item_has_next:判断list是否还有值

    用例
    <#assign seq = ["winter", "spring", "summer", "autumn"]>
    <#list seq as x>
      ${x_index + 1}. ${x}<#if x_has_next>,</#if>
    </#list>

    输出
      1. winter,
      2. spring,
      3. summer,
      4. autumn 


    include
    语法
    <#include filename>
    or
    <#include filename options>
    options包含两个属性
    encoding=”GBK” 编码格式
    parse=true 是否作为ftl语法解析,默认是true,false就是以文本方式引入.注意在ftl文件里布尔值都是直接赋值的如parse=true,而不是parse=”true”
    用例
    /common/copyright.ftl包含内容
    Copyright 2001-2002 ${me}<br>
    All rights reserved.
    模板文件
    <#assign me = "Juila Smith">
    <h1>Some test</h1>
    <p>Yeah.
    <hr>
    <#include "/common/copyright.ftl" encoding=”GBK”>
    输出结果
    <h1>Some test</h1>
    <p>Yeah.
    <hr>
    Copyright 2001-2002 Juila Smith
    All rights reserved.

    Import
    语法
    <#import path as hash>
    类似于java里的import,它导入文件,然后就可以在当前文件里使用被导入文件里的宏组件

    用例

    假设mylib.ftl里定义了宏copyright那么我们在其他模板页面里可以这样使用
    <#import "/libs/mylib.ftl" as my>

    <@my.copyright date="1999-2002"/>

    "my"在freemarker里被称作namespace

    compress
    语法
    <#compress>
      ...
    </#compress>
    用来压缩空白空间和空白的行
    用例
    <#assign x = "    moo  \n\n   ">
    (<#compress>
      1 2  3   4    5
      ${moo}
      test only

      I said, test only

    </#compress>)
    输出
    (1 2 3 4 5
    moo
    test only
    I said, test only)
    escape, noescape
    语法
    <#escape identifier as expression>
      ...
      <#noescape>...</#noescape>
      ...
    </#escape>
    用例
    主要使用在相似的字符串变量输出,比如某一个模块的所有字符串输出都必须是html安全的,这个时候就可以使用该表达式
    <#escape x as x?html>
      First name: ${firstName}
      <#noescape>Last name: ${lastName}</#noescape>
      Maiden name: ${maidenName}
    </#escape>
    相同表达式
      First name: ${firstName?html}
      Last name: ${lastName }
      Maiden name: ${maidenName?html}
    assign
    语法
    <#assign name=value>
    or
    <#assign name1=value1 name2=value2 ... nameN=valueN>
    or
    <#assign same as above... in namespacehash>
    or
    <#assign name>
      capture this
    </#assign>
    or
    <#assign name in namespacehash>
      capture this
    </#assign>
    用例
    生成变量,并且给变量赋值
    给seasons赋予序列值
    <#assign seasons = ["winter", "spring", "summer", "autumn"]>

    给变量test加1
    <#assign test = test + 1>

    给my namespage 赋予一个变量bgColor,下面可以通过my.bgColor来访问这个变量
    <#import "/mylib.ftl" as my>
    <#assign bgColor="red" in my>

    将一段输出的文本作为变量保存在x里
    下面的阴影部分输出的文本将被赋值给x
    <#assign x>
      <#list 1..3 as n>
        ${n} <@myMacro />
      </#list>
    </#assign>
    Number of words: ${x?word_list?size}
    ${x}

    <#assign x>Hello ${user}!</#assign>     error
    <#assign x=” Hello ${user}!”>         true

    同时也支持中文赋值,如:
    <#assign 语法>
      java
    </#assign>
    ${语法}
    打印输出:
    java
    global
    语法
    <#global name=value>
    or
    <#global name1=value1 name2=value2 ... nameN=valueN>
    or
    <#global name>
      capture this
    </#global>

    全局赋值语法,利用这个语法给变量赋值,那么这个变量在所有的namespace中是可见的,如果这个变量被当前的assign语法覆盖如<#global x=2> <#assign x=1> 在当前页面里x=2将被隐藏,或者通过${.global.x}来访问

    setting
    语法
    <#setting name=value>
    用来设置整个系统的一个环境
    locale
    number_format
    boolean_format
    date_format, time_format, datetime_format
    time_zone
    classic_compatible
    用例
    假如当前是匈牙利的设置,然后修改成美国
    ${1.2}
    <#setting locale="en_US">
    ${1.2}
    输出
    1,2
    1.2
    因为匈牙利是采用“,”作为十进制的分隔符,美国是用“.”



    macro, nested, return
    语法

    <#macro name param1 param2 ... paramN>
      ...
      <#nested loopvar1, loopvar2, ..., loopvarN>
      ...
      <#return>
      ...
    </#macro>
    用例
    <#macro test foo bar="Bar" baaz=-1>
      Test text, and the params: ${foo}, ${bar}, ${baaz}
    </#macro>
    <@test foo="a" bar="b" baaz=5*5-2/>
    <@test foo="a" bar="b"/>
    <@test foo="a" baaz=5*5-2/>
    <@test foo="a"/>
    输出
      Test text, and the params: a, b, 23
      Test text, and the params: a, b, -1
      Test text, and the params: a, Bar, 23
      Test text, and the params: a, Bar, -1
    定义循环输出的宏
    <#macro list title items>
      <p>${title?cap_first}:
      <ul>
        <#list items as x>
          <li>${x?cap_first}
        </#list>
      </ul>
    </#macro>
    <@list items=["mouse", "elephant", "python"] title="Animals"/>
    输出结果
    <p>Animals:
      <ul>
          <li>Mouse
          <li>Elephant
          <li>Python
      </ul>
    包含body的宏
    <#macro repeat count>
      <#list 1..count as x>
        <#nested x, x/2, x==count>
      </#list>
    </#macro>
    <@repeat count=4 ; c halfc last>
      ${c}. ${halfc}<#if last> Last!</#if>
    </@repeat>
    输出
    1. 0.5
      2. 1
      3. 1.5
      4. 2 Last!




    t, lt, rt
    语法
    <#t> 去掉左右空白和回车换行

    <#lt>去掉左边空白和回车换行

    <#rt>去掉右边空白和回车换行

    <#nt>取消上面的效果


    3一些常用方法或注意事项


    表达式转换类
    ${expression}计算expression并输出
    #{ expression }数字计算#{ expression ;format}安格式输出数字format为M和m
    M表示小数点后最多的位数,m表示小数点后最少的位数如#{121.2322;m2M2}输出121.23




    数字循环
    1..5 表示从1到5,原型number..number
    对浮点取整数
    ${123.23?int} 输出123
    给变量默认值
    ${var?default(“hello world<br>”)?html}如果var is null那么将会被hello world<br>替代

    判断对象是不是null
        <#if mouse?exists>
          Mouse found
    <#else>
    也可以直接${mouse?if_exists})输出布尔形
    常用格式化日期
    openingTime必须是Date型,详细查看freemarker文档 Reference->build-in referece->build-in for date

    ${openingTime?date}
    ${openingTime?date_time}
    ${openingTime?time}

    添加全局共享变量数据模型
    在代码里的实现
        cfg = Configuration.getDefaultConfiguration();
    cfg.setSharedVariable("global", "you good");
    页面实现可以通过global指令,具体查看指令里的global部分
    直接调用java对象的方法
    ${object.methed(args)}

    字符串处理(内置方法)
    html安全输出
    “abc<table>sdfsf”?html
    返回安全的html输出,替换掉html代码
    xml安全输出
    var?xml 
    substring的用法
    <#assign user=”hello jeen”>
    ${user[0]}${user[4]}
    ${user[1..4]}
    输出 :
    ho
    ello
    类似String.split的用法
    “abc;def;ghi”?split(“;”)返回sequence
    将字符串按空格转化成sequence,然后取sequence的长度
         var?word_list  效果同 var?split(“ ”)
    var?word_list?size

    取得字符串长度
    var?length

    大写输出字符
    var?upper_case

    小写输出字符
    var?lower_case

    首字符大写
    var?cap_first

    首字符小写
    var?uncap_first

    去掉字符串前后空格
    var?trim

    每个单词的首字符大写
    var?capitalize

    类似String.indexof:
    “babcdabcd”?index_of(“abc”) 返回1
    “babcdabcd”?index_of(“abc”,2) 返回5
    类似String.lastIndexOf
    last_index_of和String.lastIndexOf类似,同上

    下面两个可能在代码生成的时候使用(在引号前加”\”)
    j_string: 在字符串引号前加”\”
    <#assign beanName = 'The "foo" bean.'>
    String BEAN_NAME = "${beanName?j_string}";
    打印输出:
    String BEAN_NAME = "The \"foo\" bean.";
    js_string:
    <#assign user = "Big Joe's \"right hand\".">
    <script>
      alert("Welcome ${user}!");
    </script>
    打印输出
    alert("Welcome Big Joe\'s \"right hand\"!");

    替换字符串 replace
    ${s?replace(‘ba’, ‘XY’ )}
    ${s?replace(‘ba’, ‘XY’ , ‘规则参数’)}将s里的所有的ba替换成xy 规则参数包含: i r m s c f 具体含义如下:
    · i: 大小写不区分.
    · f: 只替换第一个出现被替换字符串的字符串
    · r:  XY是正则表达式
    · m: Multi-line mode for regular expressions. In multi-line mode the expressions ^ and $ match just after or just before, respectively, a line terminator or the end of the string. By default these expressions only match at the beginning and the end of the entire string.
    · s: Enables dotall mode for regular expressions (same as Perl singe-line mode). In dotall mode, the expression . matches any character, including a line terminator. By default this expression does not match line terminators.
    · c: Permits whitespace and comments in regular expressions.


    在模板里对sequences和hashes初始化
    sequences

    1. [“you”,”me”,”he”]
    2. 1..100
    3. [ {“Akey”:”Avalue”},{“Akey1”:”Avalue1”},
    {“Bkey”:”Bvalue”},{“Bkey1”:”Bvalue1”},
    ]


    hashes      {“you”:”a”,”me”:”b”,”he”:”c”}


    注释标志
    <#--
    这里是注释
    -->
    旧版本的freemarker采用的是<#comment> 注释 </#comment>方法

    sequences内置方法
    sequence?first
    返回sequence的第一个值;前提条件sequence不能是null
    sequence?last
    返回sequence最后一个值
    sequence?reverse
    反转sequence的值
    sequence?size
    返回sequence的大小
    sequence?sort
    对sequence按里面的对象toString()的结果进行排序
    sequence?sort_by(value)
    对sequence 按里面的对象的属性value进行排序
    如: sequence里面放入的是10 个user对象,user对象里面包含name,age等属性
    sequence?sort_by(name) 表示所有的user按user.name进行排序
    hashes内置方法
    hash?keys
    返回hash里的所有keys, 返回结果类型sequence
    hash?values
    返回hash里的所有value, 返回结果类型sequence
    4 freemarker在web开发中注意事项
    freemarker与webwork整合
    web中常用的几个对象
    Freemarker的ftl文件中直接使用内部对象:
    ${Request ["a"]}
    ${RequestParameters["a"]}
    ${Session ["a"]}
    ${Application ["a"]}
    ${JspTaglibs ["a"]}

    与webwork整合之后 通过配置的servlet 已经把request,session等对象置入了数据模型中
    在view中存在下面的对象
      我们可以在ftl中${req}来打印req对象
    · req - the current HttpServletRequest
    · res - the current HttpServletResponse
    · stack - the current OgnlValueStack
    · ognl - the OgnlTool instance
    · webwork - an instance of FreemarkerWebWorkUtil
    · action - the current WebWork action
    · exception - optional the Exception instance, if the view is a JSP exception or Servlet exception view
    view中值的搜索顺序
    ${name}将会以下面的顺序查找name值
    · freemarker variables
    · value stack
    · request attributes
    · session attributes
    · servlet context attributes
    在模板里ftl里使用标签
    注意,如果标签的属性值是数字,那么必须采用nubmer=123方式给属性赋值
    JSP页面
    <%@page contentType="text/html;charset=ISO-8859-2" language="java"%>
    <%@taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
    <%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>

    <html>
      <body>
        <h1><bean:message key="welcome.title"/></h1>
        <html:errors/>
        <html:form action="/query">
          Keyword: <html:text property="keyword"/><br>
          Exclude: <html:text property="exclude"/><br>
          <html:submit value="Send"/>
        </html:form>
      </body>
    </html>
    模板ftl页面
    <#assign html=JspTaglibs["/WEB-INF/struts-html.tld"]>
    <#assign bean=JspTaglibs["/WEB-INF/struts-bean.tld"]>

    <html>
      <body>
        <h1><@bean.message key="welcome.title"/></h1>
        <@html.errors/>
        <@html.form action="/query">
          Keyword: <@html.text property="keyword"/><br>
          Exclude: <@html.text property="exclude"/><br>
          <@html.submit value="Send"/>
        </@html.form>
      </body>
    </html>


    如何初始化共享变量
    1. 初始化全局共享数据模型
    freemark在web上使用的时候对共享数据的初始化支持的不够,不能在配置初始化的时候实现,而必须通过ftl文件来初始化全局变量。这是不能满主需求的,我们需要在servlet init的时候留出一个接口来初始化系统的共享数据
    具体到和webwork整合,因为本身webwork提供了整合servlet,如果要增加全局共享变量,可以通过修改 com.opensymphony.webwork.views.freemarker.FreemarkerServlet来实现,我们可以在这个 servlet初始化的时候来初始化全局共享变量
    与webwork整合配置
    配置web.xml
    <servlet>
        <servlet-name>freemarker</servlet-name>
        <servlet-class>com.opensymphony.webwork.views.freemarker.FreemarkerServlet</servlet-class>
        <init-param>
          <param-name>TemplatePath</param-name>
    <param-value>/</param-value>
    <!—模板载入文件夹,这里相对context root,递归获取该文件夹下的所有模板-->
        </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>
    <!—模板更新时间,0表示每次都更新,这个适合开发时候-->
          <param-value>0</param-value>
        </init-param>
        <init-param>
          <param-name>default_encoding</param-name>
          <param-value>GBK</param-value>
        </init-param>
        <init-param>
          <param-name>number_format</param-name>
          <param-value>0.##########</param-value><!—数字显示格式-->
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>freemarker</servlet-name>
        <url-pattern>*.ftl</url-pattern>
      </servlet-mapping>

    5高级方法
    自定义方法
    ${timer("yyyy-MM-dd H:mm:ss", x)}
    ${timer("yyyy-MM-dd ", x)}

    在模板中除了可以通过对象来调用方法外(${object.methed(args)})也可以直接调用java实现的方法,java类必须实现接口TemplateMethodModel的方法exec(List args). 下面以把毫秒的时间转换成按格式输出的时间为例子
    public class LongToDate implements TemplateMethodModel {
      
    public TemplateModel exec(List args) throws TemplateModelException {
    SimpleDateFormat mydate = new SimpleDateFormat((String) args.get(0)));
            return mydate.format(new Date(Long.parseLong((String)args.get(1)));
        }
    }
    将LongToDate对象放入到数据模型中
    root.put("timer", new IndexOfMethod());
    ftl模板里使用
    <#assign x = "123112455445">
    ${timer("yyyy-MM-dd H:mm:ss", x)}
    ${timer("yyyy-MM-dd ", x)}

    输出
    2001-10-12 5:21:12
    2001-10-12

    自定义 Transforms
    实现自定义的<@transform>文本或表达式</@transform>的功能,允许对中间的最终文本进行解析转换

    例子:实现<@upcase>str</@upcase> 将str转换成STR 的功能

    代码如下:
    import java.io.*;
    import java.util.*;
    import freemarker.template.TemplateTransformModel;

    class UpperCaseTransform implements TemplateTransformModel {

        public Writer getWriter(Writer out, Map args) {
            return new UpperCaseWriter(out);
        }

        private class UpperCaseWriter extends Writer {
         
            private Writer out;
             
            UpperCaseWriter (Writer out) {
                this.out = out;
            }

            public void write(char[] cbuf, int off, int len)
                    throws IOException {
                out.write(new String(cbuf, off, len).toUpperCase());
            }

            public void flush() throws IOException {
                out.flush();
            }

            public void close() {
            }
        }
    }
    然后将此对象put到数据模型中
    root.put("upcase", new UpperCaseTransform());

    在view(ftl)页面中可以如下方式使用

    <@upcase>
    hello world
    </@upcase>

    打印输出:
    HELLO WORLD
    展开全文
  • FreeMarker语言 FreeMarker语言概述 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。 FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序 虽然FreeMarker...

    FreeMarker语言

    FreeMarker语言概述

    FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。

    FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序

    虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据(如下图)

    FreeMarker不是一个Web应用框架,而适合作为Web应用框架一个组件。

    FreeMarker与容器无关,因为它并不知道HTTP或Servlet;FreeMarker同样可以应用于非Web应用程序环境。

    FreeMarker更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用JSP标记库。

    FreeMarker是免费的。

    FreeMarker特性

    通用目标

    能够生成各种文本:HTML、XML、RTF、Java源代码等等

    易于嵌入到你的产品中:轻量级;不需要Servlet环境

    插件式模板载入器:可以从任何源载入模板,如本地文件、数据库等等

    你可以按你所需生成文本:保存到本地文件;作为Email发送;从Web应用程序发送它返回给Web浏览器

    强大的模板语言

    所有常用的指令:include、if/elseif/else、循环结构

    在模板中创建和改变变量

    几乎在任何地方都可以使用复杂表达式来指定值

    命名的宏,可以具有位置参数和嵌套内容

    名字空间有助于建立和维护可重用的宏库,或者将一个大工程分成模块,而不必担心名字冲突

    输出转换块:在嵌套模板片段生成输出时,转换HTML转义、压缩、语法高亮等等;你可以定义自己的转换

    通用数据模型

    FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在模板中显示

    你可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等等),告诉模板开发者使用方法,使其不受技术细节的打扰

    为Web准备

    在模板语言中内建处理典型Web相关任务(如HTML转义)的结构

    能够集成到Model2 Web应用框架中作为JSP的替代

    支持JSP标记库

    为MVC模式设计:分离可视化设计和应用程序逻辑;分离页面设计员和程序员

    智能的国际化和本地化

    字符集智能化(内部使用UNICODE)

    数字格式本地化敏感

    日期和时间格式本地化敏感

    非US字符集可以用作标识(如变量名)

    多种不同语言的相同模板

    强大的XML处理能力

    <#recurse> 和<#visit>指令(2.3版本)用于递归遍历XML树。在模板中清楚和直觉的访问XML对象模型。开源论坛 JForum 就是使用了 FreeMarker 做为页面模板。

    第一个FreeMarker程序

    1.      建立一个普通的java项目:testFreeMarker

    2.      引入freemarker.jar包

    3.      在项目目录下建立模板目录:templates

    4.      在templates目录下,建立a.ftl模板文件,内容如下:

     

    你好啊,${user},今天你的精神不错!

     

    5.      建立com.sxt.test.freemarker包,然后建立Test1.java文件,内容如下:

    package com.sxt.test.freemarker;

     

    import java.io.File;

    import java.io.OutputStreamWriter;

    import java.io.Writer;

    import java.util.HashMap;

    import java.util.Map;

     

    import freemarker.template.Configuration;

    import freemarker.template.DefaultObjectWrapper;

    import freemarker.template.Template;

     

    public class Test1 {

             public static void main(String[] args) throws Exception {

                       //创建Freemarker配置实例

                       Configuration cfg = new Configuration();

                      

                       cfg.setDirectoryForTemplateLoading(new File("templates"));

                      

                       //创建数据模型

                       Map root = new HashMap();

                       root.put("user", "老高");

                      

                       //加载模板文件

                       Template t1 = cfg.getTemplate("a.ftl");

                      

                       //显示生成的数据,//将合并后的数据打印到控制台

           Writer out = new OutputStreamWriter(System.out);

           t1.process(root, out);

           out.flush();

     

           //显示生成的数据,//将合并后的数据直接返回成字符串!

    //     StringWriter out = new StringWriter();  

    //     t1.process(root, out);

    //     out.flush();

    //     String temp = out.toString();

    //     System.out.println(temp);        }

    }

    6.      编译和运行Test1.java文件,控制台打印:

     

    数据类型

    一、直接指定值

    直接指定值可以是字符串、数值、布尔值、集合及Map对象。
    1. 字符串
    直接指定字符串值使用单引号或双引号限定。字符串中可以使用转义字符”\"。如果字符串内有大量的特殊字符,则可以在引号的前面加上一个字母r,则字符串内的所有字符都将直接输出。

    2. 数值
    数值可以直接输入,不需要引号。FreeMarker不支持科学计数法。

    3. 布尔值
    直接使用true或false,不使用引号。

    4. 集合
    集合用中括号包括,集合元素之间用逗号分隔。
    使用数字范围也可以表示一个数字集合,如1..5等同于集合[1, 2, 3, 4, 5];同样也可以用5..1来表示[5, 4, 3, 2, 1]。

    5. Map对象
    Map对象使用花括号包括,Map中的key-value对之间用冒号分隔,多组key-value对之间用逗号分隔。
    注意:Map对象的key和value都是表达式,但key必须是字符串。

     

    6. 时间对象

    root.put("date1",new Date());

    ${date1?string("yyyy-MM-dd HH:mm:ss")}

     

    7. JAVABEAN的处理

             Freemarker中对于javabean的处理跟EL表达式一致,类型可自动转化!非常方便!

    二、输出变量值

    FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性。

    1. 顶层变量
    所谓顶层变量就是直接放在数据模型中的值。输出时直接用${variableName}即可。

    2. 输出集合元素
    可 以根据集合元素的索引来输出集合元素,索引用中括号包括。如: 输出[“1”, “2”, “3”]这个名为number的集合,可以用${number[0]}来输出第一个数字。FreeMarker还支持用number[1..2]来表示原 集合的子集合[“2”, “3”]。

    3. 输出Map元素
    对于JavaBean实例,FreeMarker一样把它看作属性为key,属性值为value的Map对象。
    输出Map对象时,可以使用点语法或中括号语法,如下面的几种写法的效果是一样的:
                book.author.name                                                                                                                    
                book.author["name"]                                                                                                                    
                book["author"].name                                                                                                                     
                book["author"]["name"]                                                                                                                  
    使用点语法时,变量名字有和顶层变量一样的限制,但中括号语法没有任何限制。

    三、字符串操作

    1. 字符串连接
    字符串连接有两种语法:
    (1)使用${..}或#{..}在字符串常量内插入表达式的值;
    (2)  直接使用连接运算符“+”连接字符串。
    如,下面两种写法等效:
                 ${"Hello,${user}"}                                                                                                               
                 ${"Hello, " + user +"!"}                                                                                                        
    有一点需要注意: ${..}只能用于文本部分作为插值输出,而不能用于比较等其他用途,如:
                 <#if ${isBig}>Wow!</#if>                                                                                                              
                 <#if"${isBig}">Wow!</#if>                                                                                                            
    应该写成:
                 <#ifisBig>Wow!</#if>                                                                                                                  

    2. 截取子串
    截取子串可以根据字符串的索引来进行,如果指定一个索引值,则取得字符串该索引处的字符;如果指定两个索引值,则截取两个索引中间的字符串子串。如:
                 <#assign number="01234">
                 ${number[0]} <#-- 输出字符0-->
                  ${number[0..3]}<#-- 输出子串“0123”-->

     

    四、集合连接操作
          连接集合的运算符为“+”

    五、Map连接操作
       Map连接操作的运算符为“+”

    六、算术运算符
       FreeMarker表达式中支持“+”、“-”、“*”、“/”、“%”运算符。

    七、比较运算符

    表达式中支持的比较运算符有如下几种:
    1. =(或者==):判断两个值是否相等;
    2. !=:判断两个值是否不相等;
    注: =和!=可以用作字符串、数值和日期的比较,但两边的数据类型必须相同。而且FreeMarker的比较是精确比较,不会忽略大小写及空格。
    3. >(或者gt):大于
    4. >=(或者gte):大于等于
    5. <(或者lt):小于
    6. <=(或者lte):小于等于
    注: 上面这些比较运算符可以用于数字和日期,但不能用于字符串。大部分时候,使用gt比>有更好的效果,因为FreeMarker会把>解释成标签的结束字符。可以使用括号来避免这种情况,如:<#if (x>y)>。

    if else 语句测试:

    <#if num0 gt 18>  <#--不是使用>,大部分时候,freemarker会把>解释成标签结束! -->

        及格!

    <#else>

        不及格!

    </#if>

    root.put("num0", 18);

     

    八、逻辑运算符

    1. &&: 逻辑与;
    2. ||:逻辑或;
    3. !:逻辑非
    逻辑运算符只能用于布尔值。

    九、内建函数

    FreeMarker提供了一些内建函数来转换输出,可以在任何变量后紧跟?,?后紧跟内建函数,就可以通过内建函数来转换输出变量。

    字符串相关常用的内建函数:
    1. html:对字符串进行HTML编码;
    2. cap_first:使字符串第一个字母大写;
    3. lower_case:将字符串转成小写;
    4. upper_case:将字符串转成大写;

    集合相关常用的内建函数:
    1. size:获得集合中元素的个数;

    数字值相关常用的内建函数:
    1. int:取得数字的整数部分。

     

    举例:

    root.put("htm2","<b>粗体</b>");

    内建函数:

    ${htm2?html}

     

    十、空值处理运算符

    FreeMarker的变量必须赋值,否则就会抛出异常。而对于FreeMarker来说,null值和不存在的变量是完全一样的,因为FreeMarker无法理解null值。
    FreeMarker提供两个运算符来避免空值:
    1. !:指定缺失变量的默认值;
    2. ??:判断变量是否存在。
    !运算符有两种用法:variable!或variable!defaultValue。第一种用法不给变量指定默认值,表明默认值是空字符串、长度为0的集合、或长度为0的Map对象。
    使用!运算符指定默认值并不要求默认值的类型和变量类型相同。

    测试空值处理:

    <#-- ${sss} 没有定义这个变量,会报异常! -->

    ${sss!} <#--没有定义这个变量,默认值是空字符串! -->

    ${sss!"abc"} <#--没有定义这个变量,默认值是字符串abc! -->

     

             ??运算符返回布尔值,如:variable??,如果变量存在,返回true,否则返回false。

            

     

    数据类型常见示例

     直接指定值

       字符串 : "Foo"或 者'Foo'或"It's\"quoted\""或r"C:\raw\string"

       数字:123.45

       布尔值:true,false

       序列:["foo","bar", 123.45], 1..100

       哈希表:{"name":"greenmouse", "price":150}

       检索变量    顶层变量:user

       从哈希表中检索数据:user.name,user[“name”]

       从序列中检索:products[5]

       特殊变量:.main

       字符串操作

       插值(或连接):"Hello${user}!"(或"Free" + "Marker")

       获取一个字符:name[0]

       序列操作

       连接:users +["guest"]

       序列切分:products[10..19]  或  products[5..]

       哈希表操作

       连接:passwords+ {"joe":"secret42"}

       算数运算: (x *1.5 + 10) / 2 - y % 100

       比 较 运 算 : x == y,   x != y,  x < y,   x > y,   x >= y,  x <= y,

    x &lt; y,  等等

        逻辑操作:!registered&& (firstVisit || fromEurope)

        内建函数:name?upper_case

        方法调用:repeat("What",3)

       处理不存在的值

       默认值:name!"unknown"  或者(user.name)!"unknown"  或者

    name! 或者  (user.name)!

       检测不存在的值:name??或者(user.name)??

            参考:运算符的优先级

    模板开发语句

    最简单的模板是普通  HTML  文件(或者是其他任何文本文件—FreeMarker  本身不属于HTML)。当客户端访问页面时,FreeMarker要发送 HTML 代码至客户端浏览器端显示。如果想要页面动起来,就要在 HTML 中放置能被 FreeMarker 所解析的特殊部分。

       

    ${…}:FreeMarker 将会输出真实的值来替换花括号内的表达式,这样的表达式被称为

    interpolations 插值,可以参考第上面示例的内容。

     

       FTL tags 标签(FreeMarker  模板的语言标签):FTL 标签和 HTML 标签有一点相似,但是它们是  FreeMarker 的指令而且是不会直接输出出来的东西。这些标签的使用一般以符号#开头。(用户自定义的 FTL 标签使用@符号来代替#,但这是更高级的主题内容了,后面会详细地讨论)

      

    Comments 注释:FreeMarker的注释和 HTML 的注释相似,但是它用<#--和-->来分隔的。任何介于这两个分隔符(包含分隔符本身)之间内容会被 FreeMarker  忽略,就不会

    输出出来了。

     

        其他任何不是  FTL  标签,插值或注释的内容将被视为静态文本,这些东西就不会被

    FreeMarker 所解析,会被按照原样输出出来。

     

       directives指令:就是所指的  FTL  标签。这些指令在  HTML  的标签(如<table>和

    </table>)和 HTML 元素(如 table 元素)中的关系是相同的。(如果现在你还不能区

    分它们,那么把“FTL 标签”和“指令”看做是同义词即可。)

    if指令

    root.put("random",new Random().nextInt(100));

    ------------------------------------------------

    if语句测试:

    ${user}是<#if user=="老高">我们的老师</#if>

    ------------------------------------------------

    if else 语句测试:

    <#if num0 gt 18>  <#--不是使用>,大部分时候,freemarker会把>解释成标签结束! -->

        及格!

    <#else>

        不及格!

    </#if>

    ---------------------------------------------------

    if else if else语句测试:

    <#if random gte 90>

        优秀!

    <#elseif random gte 80>

        良好!

    <#else>

        一般! 

    </#if>

    ----------------------------------------------------

     

     

    list指令

           List list = new ArrayList();

           list.add(new Address("中国","北京"));

           list.add(new Address("中国","上海"));

           list.add(new Address("美国","纽约"));

           root.put("lst", list);

    测试list指令:

    <#list lst as dizhi >

        <b>${dizhi.country}</b> <br/>

    </#list>

     

    思考问题:<c:forEach> status属性。在此处如何实现?

                                                                                             想了解更多加微信公众号(jblPaul)

                                                                                                       

    控制台打印:

    测试list语句:

        <b>中国</b> <br/>

        <b>中国</b> <br/>

        <b>美国</b> <br/>

     

    include指令

    增加被包含文件,放于templates目录下:

    文件内容如下:

     

     

    模板文件中代码如下:

    测试include指令:

    <#include "included.txt" />

     

     

    自定义指令(macro指令)

    <#macro m1>   <#--定义指令m1 -->

        <b>aaabbbccc</b>

        <b>dddeeefff</b>

    </#macro>

    <@m1 /><@m1 />  <#--调用上面的宏指令 -->

     

    定义带参的宏指令:

    <#macro m2 a b c >

        ${a}--${b}--${c}

    </#macro>

    <@m2 a="老高" b="老张" c="老马" />

     

    nested指令:

    <#macro border>

      <table border=4 cellspacing=0cellpadding=4><tr><td>

        <#nested>

      </td></tr></table>

    </#macro>

    <@border >表格中的内容!</@border>

     

    欧阳鸿:宏指令中,有没有类似于方法的返回值?

    命名空间

    当运行 FTL 模板时,就会有使用assign 和 macro 指令创建的变量的集合(可能是空的),可以从前一章节来看如何使用它们。像这样的变量集合被称为 namespace 命名空间。在简单的情况下可以只使用一个命名空间,称之为 main namespace 主命名空间。因为通常只使用本页上的命名空间,所以就没有意识到这点。

        如果想创建可以重复使用的宏,函数和其他变量的集合,通常用术语来说就是引用

    library 库。使用多个命名空间是必然的。只要考虑你在一些项目中,或者想和他人共享使用的时候,你是否有一个很大的宏的集合。但要确保库中没有宏(或其他变量)名和数据模型中变量同名,而且也不能和模板中引用其他库中的变量同名。通常来说,变量因为名称冲突也会相互冲突。所以要为每个库中的变量使用不同的命名空间。

     

    定义b.ftl文件:

    <#macro copyright date>

      <p>Copyright (C) ${date} 北京尚学堂.</p>

    </#macro>

    <#assign mail = "bjsxt@163.com">

     

    在a.ftl文件中引入b.ftl,从而可以使用b.ftl中定义的宏和变量:

    测试命名空间:

    <#import "b.ftl" as bb  />

    <@bb.copyright date="2010-2011" />

    ${bb.mail}

    <#assign mail="my@163.com"  />

    ${mail}

    <#assign mail="my@163.com" in bb  />

    ${bb.mail}

     

    执行后,控制台打印:

    测试命名空间:

      <p>Copyright (C) 2010-2011 北京尚学堂.</p>

    bjsxt@163.com

    my@163.com

    my@163.com

     

    命名空间命名规则

    如果你为 Example 公司工作,它们拥有 www.example.com 网的主页,你的工作是开发

    一个部件库,那么要引入你所写的 FTL 的路径应该是:

    /lib/example.com/widget.ftl

     

    注意到 www 已经被省略了。第三次路径分割后的部分可以包含子目录,可以像下面这

    样写:

            /lib/example.com/commons/string.ftl

    一个重要的规则就是路径不应该包含大写字母,为了分隔词语,使用下划线_,就像

    wml_form(而不是 wmlForm)。

     

    如果你的工作不是为公司或组织开发库,也要注意,你应该使用项目主页的 URL,比如

    /lib/example.sourceforge.net/example.ftl或/lib/geocities.com/jsmith/example.ftl。

     

    在Servlet中使用Freemarker

    参考Freemarker包中example目录下webapp1项目!

     

    struts2中整合FreeMarker

    1.解压struts2-core-X.X.X.jar文件,把在META-INF文件夹下面的struts-tags.tld文件复制到WEB-INF文件夹下。   将freemark的jar导入到工程中

     

    2.在web.xml文件中配置freemark同时启动JSPSupportServlet.代码如下:

    <servlet>
            <servlet-name>freemarker</servlet-name>
            <servlet-class>
                freemarker.ext.servlet.FreemarkerServlet
            </servlet-class>
            <!--下面的配置freemarke的ftl文件的位置 -->
            <init-param>
                <param-name>TemplatePath</param-name>
                <param-value>/</param-value>
            </init-param>
            <!-- 是否和服务器(tommcat)一起启动。-->
            <load-on-startup>1</load-on-startup>
        </servlet>

        <servlet-mapping>
            <servlet-name>freemarker</servlet-name>
            <url-pattern>*.ftl</url-pattern>
        </servlet-mapping>


    <servlet>
      <!-- define a JspSupportServlet Object -->
      <servlet-name>JspSupportServlet</servlet-name>
      <servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>
      <!-- setting JspSupportServlet auto start -->
      <load-on-startup>1</load-on-startup>
     </servlet>

     

    3.在FreeMarker模板中使用assign指令导入标签库。代码如下

    <#assign s=JspTaglibs["/WEB-INF/struts-tags.tld"] /> 注:这里我把struts-tags.tld放在WEB-INF下面

    if

     

    详情可见web项目:testFreeMarker2

     

     

     

    作业:

    1.      使用list标签遍历list容器时,如何获取索引(下划线加index即可获取):

     

    -------------------------------------

    测试list索引_index

    <#list list as city>

             ${city}<br/>${city_index}

             <#if city_index==1>

                       <#break>

             </#if>

    </#list>

    **************************************

    测试list中国_has_next

    <#list list as city>

             ${city}<br/>${city_index}

             <#if city_has_next>

                       我有下一项!------- ${city_index}

             </#if>

    </#list>

     

    2.      调用对象或类的方法?

    3.      .main特殊变量的作用

    4.      定义的macro能否有返回值,有的话,怎么处理?

     

     

     

     

    =======================华丽分割线================

    1、对activityMenu (集合对象)进行遍历:

     

     

    知识点:集合对象判空、集合遍历、使用索引、if条件判断

     

    2、${MenuList?size}  ——>得到List集合的个数。  <#if (a_list?size >= 15)> :  判断大小

     

    3、如果是Long类型会有”,”区分,处理方式${c_List.refId?c}  

                                                                               想了解更多加微信公众号(jblPaul)

                                                                                                       

     

    展开全文
  • Freemarker使用教程——入门篇

    万次阅读 多人点赞 2017-07-25 18:12:57
    一.简介 FreeMarker 是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯 Java 编写,FreeMarker 被设计用来生成 HTML Web 页面,特别是基于 MVC 模式的应用程序,虽然 FreeMarker ...FreeMarker 不是一个 W

    一.简介

    FreeMarker 是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯 Java 编写,FreeMarker 被设计用来生成 HTML Web 页面,特别是基于 MVC 模式的应用程序,虽然 FreeMarker 具有一些编程的能力,但通常由 Java 程序准备要显示的数据,由FreeMarker 生成页面,通过模板显示准备的数据

    FreeMarker 不是一个 Web 应用框架,而适合作为 Web 应用框架一个组件。FreeMarker 与容器无关,因为它并不知道 HTTP 或 Servlet;FreeMarker 同样可以应用于非Web应用程序环境,FreeMarker 更适合作为 Model2 框架(如 Struts)的视图组件,你也可以在模板中使用 JSP标记库。另外,FreeMarker是免费的。


    2.应用场景

    比较适合运用在访问量大(或页面数据量大),但是数据很少与后台进行交互(即对实时性要求不是很高的)的页面,比如商品网站上的商品详情页等。


    3.前期准备

    要想使用freemarker,首先必须要有freemarker的jar包,这个互联网上随处可以下载,这边就不多说

    <dependency>
    <groupId>freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.9</version>
    </dependency>
    



    4.入门demo

    (1)创建一个testFreemarker类

    import java.io.File;
    import java.io.FileWriter;
    import java.io.Writer;
    import java.util.HashMap;
    import java.util.Map;
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    
    
    /**
     * @作者:JackHisen(GWD)
     * @项目名:freemarker
     * @时间:2017-7-25 下午2:39:45
     * @version 1.0
     */
    public class testFreemarker {
    	public static void main(String[] args) throws Exception {
    		String dir="H:\\Java-EE Workspace\\freemarker\\src\\com\\gwd\\freemarker";
    		Configuration conf = new Configuration();
    		//加载模板文件(模板的路径)
    		conf.setDirectoryForTemplateLoading(new File(dir));
    		// 加载模板
    		Template template = conf.getTemplate("/freemarker-demo.ftl");
    		// 定义数据
    		
    		Map root = new HashMap();
                    root.put("world", "Hello World");
    		// 定义输出
    		Writer out = new FileWriter(dir + "/freemarker.html");
    		template.process(root, out);
    		System.out.println("转换成功");
    		out.flush();
    		out.close();
    	}
    }
    

    项目目录如下,其中freemarker.html文件是运行main函数后自动生成的,freemarker-demo.ftl为模板


    (2)freemarker模板中写入内容


    (3)生成的html页面:



    5.其他数据类型

    1.实体bean

    (1)创建Person类

    public class Person {
    	private int id;
    	private String name;
    	public int getId() {
    		return id;
    	}
    	public void setId(int id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    }
    
    (2)testFreemarker
    public class testFreemarker {
    	public static void main(String[] args) throws Exception {
    		String dir="H:\\Java-EE Workspace\\freemarker\\src\\com\\gwd\\freemarker";
    		Configuration conf = new Configuration();
    		//加载模板文件(模板的路径)
    		conf.setDirectoryForTemplateLoading(new File(dir));
    		// 加载模板
    		Template template = conf.getTemplate("/freemarker-demo.ftl");
    		// 定义数据
    		
    		Person person=new Person();
    		person.setId(1);
    		person.setName("小明");
    		Map root = new HashMap();
    		root.put("person", person);
    		// 定义输出
    		Writer out = new FileWriter(dir + "/freemarker.html");
    		template.process(root, out);
    		System.out.println("转换成功");
    		out.flush();
    		out.close();
    	}
    }

    (3)Freemarker模板

    ${person.id}
    ${person.name}

    (4)生成的html页面



    2.List集合

    (1)testFreemarker

    public class testFreemarker {
    	public static void main(String[] args) throws Exception {
    		String dir="H:\\Java-EE Workspace\\freemarker\\src\\com\\gwd\\freemarker";
    		Configuration conf = new Configuration();
    		//加载模板文件(模板的路径)
    		conf.setDirectoryForTemplateLoading(new File(dir));
    		// 加载模板
    		Template template = conf.getTemplate("/freemarker-demo.ftl");
    		// 定义数据
    		
    		Person p1=new Person();
    		p1.setId(1);
    		p1.setName("小明");
    		Person p2=new Person();
    		p2.setId(2);
    		p2.setName("小华");
    		List<Person> person=new ArrayList<Person>();
    		person.add(p1);
    		person.add(p2);
    		Map root = new HashMap();
    		root.put("person", person);
    		// 定义输出
    		Writer out = new FileWriter(dir + "/freemarker.html");
    		template.process(root, out);
    		System.out.println("转换成功");
    		out.flush();
    		out.close();
    	}
    }

    (2)模板

    <#list person as p>
    ${p.id}/${p.name}
    </#list>

    (3)生成的html文件



    3.Map集合

    1.testFreemarker

    public class testFreemarker {
    	public static void main(String[] args) throws Exception {
    		String dir="H:\\Java-EE Workspace\\freemarker\\src\\com\\gwd\\freemarker";
    		Configuration conf = new Configuration();
    		//加载模板文件(模板的路径)
    		conf.setDirectoryForTemplateLoading(new File(dir));
    		// 加载模板
    		Template template = conf.getTemplate("/freemarker-demo.ftl");
    		// 定义数据
    		
    		Map root = new HashMap();
    		Map mxs = new HashMap();
    		mxs.put("fbb","范冰冰");
    		mxs.put("lbb","李冰冰");
    
    		root.put("mxs",mxs);
    
    		// 定义输出
    		Writer out = new FileWriter(dir + "/freemarker.html");
    		template.process(root, out);
    		System.out.println("转换成功");
    		out.flush();
    		out.close();
    	}
    }
    

    2.模板(两种写法)

    ${mxs.fbb}/${mxs.lbb}
    
    
    <#list mxs?keys as k>
       ${mxs[k]}
    </#list>
    

    3.生成的html



    4.List<Map>集合

    1.testFreemarker

    public class testFreemarker {
    	public static void main(String[] args) throws Exception {
    		String dir="H:\\Java-EE Workspace\\freemarker\\src\\com\\gwd\\freemarker";
    		Configuration conf = new Configuration();
    		//加载模板文件(模板的路径)
    		conf.setDirectoryForTemplateLoading(new File(dir));
    		// 加载模板
    		Template template = conf.getTemplate("/freemarker-demo.ftl");
    		// 定义数据
    		
    		Map root = new HashMap();
    		List<Map> maps = new ArrayList<Map>();
    		Map pms1 = new HashMap();
    		pms1.put("id1", "范冰冰");
    		pms1.put("id2", "李冰冰");
    		Map pms2 = new HashMap();
    		pms2.put("id1", "曾志伟");
    		pms2.put("id2", "何炅");
    		maps.add(pms1);
    		maps.add(pms2);
    		root.put("maps", maps);
    
    		// 定义输出
    		Writer out = new FileWriter(dir + "/freemarker.html");
    		template.process(root, out);
    		System.out.println("转换成功");
    		out.flush();
    		out.close();
    	}
    }
    
    2.模板(2种)

    <#list maps as m>
    	${m.id1}/${m.id2}
    </#list>
    
    
    <#list maps as m>
    	<#list m?keys as k>
    		${m[k]}
    	</#list>
    </#list>
    

    3.生成的html


    5.获得当前迭代的索引

    (1)testFreemarker

    public class testFreemarker {
    	public static void main(String[] args) throws Exception {
    		String dir="H:\\Java-EE Workspace\\freemarker\\src\\com\\gwd\\freemarker";
    		Configuration conf = new Configuration();
    		//加载模板文件(模板的路径)
    		conf.setDirectoryForTemplateLoading(new File(dir));
    		// 加载模板
    		Template template = conf.getTemplate("/freemarker-demo.ftl");
    		// 定义数据
    		
    		Map root = new HashMap();
    		Person p1=new Person();
    		p1.setId(1);
    		p1.setName("李冰冰");
    		Person p2=new Person();
    		p2.setId(2);
    		p2.setName("范冰冰");
    		Person p3=new Person();
    		p3.setId(3);
    		p3.setName("沙冰冰");
    		List<Person> list = new ArrayList<Person>();
    		list.add(p1);
    		list.add(p2);
    		list.add(p3);
    		root.put("persons", list);
    
    		// 定义输出
    		Writer out = new FileWriter(dir + "/freemarker.html");
    		template.process(root, out);
    		System.out.println("转换成功");
    		out.flush();
    		out.close();
    	}
    }
    

    (2)模板

    <#list persons as p>
    	${p_index}
    </#list>
    

    (3)生成的html文件




    (6)在模板中进行赋值

    (1)testFreemarker

    package com.gwd.freemarker;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.io.Writer;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    
    
    /**
     * @作者:JackHisen(GWD)
     * @项目名:freemarker
     * @时间:2017-7-25 下午2:39:45
     * @version 1.0
     */
    public class testFreemarker {
    	public static void main(String[] args) throws Exception {
    		String dir="H:\\Java-EE Workspace\\freemarker\\src\\com\\gwd\\freemarker";
    		Configuration conf = new Configuration();
    		//加载模板文件(模板的路径)
    		conf.setDirectoryForTemplateLoading(new File(dir));
    		// 加载模板
    		Template template = conf.getTemplate("/freemarker-demo.ftl");
    		// 定义数据
    		
    		Map root = new HashMap();
    		
    		root.put("world","hello world");
    
    		// 定义输出
    		Writer out = new FileWriter(dir + "/freemarker.html");
    		template.process(root, out);
    		System.out.println("转换成功");
    		out.flush();
    		out.close();
    	}
    }
    
    

    (2)模板

    <#assign x="${world}" />
    ${x}
    
    <#assign x>
       <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n>
          ${n}
       </#list>
    </#assign>
    ${x}
    

    (3)生成的html


    7.if语句

    (1)申明:一般情况下模板中的数据来源于后台,但是这边为了方便演示,所以数据都在模板中写死了,后台testFreemarker可以同上,但实际上map可以为空,只要确保能生成html页面即可

    (2)模板

    <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n>
    <#if n != "星期一">
       ${n}
    </#if>
    </#list>


    (3)生成的html文件



    8.else语句

    (1)模板

    <#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n>
    <#if (n_index == 1) || (n_index == 3)>
       ${n} --红色
    <#else>
    ${n} --绿色
    </#if>
    </#list>
    

    (2)生成的html


    9.格式化日期

    (1)testFreemarker

    public class testFreemarker {
    	public static void main(String[] args) throws Exception {
    		String dir="H:\\Java-EE Workspace\\freemarker\\src\\com\\gwd\\freemarker";
    		Configuration conf = new Configuration();
    		//加载模板文件(模板的路径)
    		conf.setDirectoryForTemplateLoading(new File(dir));
    		// 加载模板
    		Template template = conf.getTemplate("/freemarker-demo.ftl");
    		// 定义数据
    		
    		Map root = new HashMap();
    		
    		root.put("cur_time",new Date());
    			
    		// 定义输出
    		Writer out = new FileWriter(dir + "/freemarker.html");
    		template.process(root, out);
    		System.out.println("转换成功");
    		out.flush();
    		out.close();
    	}
    }
    
    

    (2)日期模板

    ${cur_time?date}
    生成html



    (3)日期时间模板

    ${cur_time?datetime}
    生成html


    (4)时间模板

    ${cur_time?time}
    

    生成html


    10.对null的处理

    (1)testFreemarker

    public class testFreemarker {
    	public static void main(String[] args) throws Exception {
    		String dir="H:\\Java-EE Workspace\\freemarker\\src\\com\\gwd\\freemarker";
    		Configuration conf = new Configuration();
    		//加载模板文件(模板的路径)
    		conf.setDirectoryForTemplateLoading(new File(dir));
    		// 加载模板
    		Template template = conf.getTemplate("/freemarker-demo.ftl");
    		// 定义数据
    		
    		Map root = new HashMap();
    		
    		root.put("world",null);
    			
    		// 定义输出
    		Writer out = new FileWriter(dir + "/freemarker.html");
    		template.process(root, out);
    		System.out.println("转换成功");
    		out.flush();
    		out.close();
    	}
    }

    (2)null为空模板

    ${world!}         ——前面有个null
    生成html



    (3)为null时给默认值模板

    ${world!"如果world为null,我就会显示"}
    
    生成的html


    11.宏定义

    (1)普通宏定义

    模板:

    <#macro table u>
    ${u} 
    </#macro>
    <@table u="这个是宏定义" />

    生成的html


    (2)扩展宏定义

    模板:

    <#macro table u>
     ${u}
    <#nested/>
    </#macro>
    <@table u=8 >我是扩展的宏定义</@table>
    
    
    生成的html


    展开全文
  • FreeMarker

    万次阅读 2018-06-18 17:56:12
    1.什么是FreeMarkerFreeMarker是一款模板引擎,一种开源的、基于模板的、用来生成/输出文本的通用工具。 它不是面向最终用户的,不是Web应用框架,它是Java的一个类库,是Web应用框架中的一个实用的组件,是一款...

    1.什么是FreeMarker?

    FreeMarker是一款模板引擎,一种开源的、基于模板的、用来生成/输出文本的通用工具。
    它不是面向最终用户的,不是Web应用框架,它是Java的一个类库,是Web应用框架中的一个实用的组件,是一款可以嵌入开发产品的一款应用程序。
    FreeMarker的设计是被用来生成HTML页面,尤其是通过基于实现了MVC模式的Servlet应用程序。
    使用MVC模式的动态网页的构思,使得你可以将前端设计从程序中分离出来,更加贴合java的各司其职的编程思想,使得代码更简洁且便于维护。
    尽管FreeMarker也有编程能力,但它也不像PHP那样的一种全面的编程语言。
    一般我们只使用FreeMarker的模板生成个文本来呈现早已准备好的数据,它仅仅来生成文本,它也非常适用于非 Web应用环境的开发。

    要注意的是,我们使用FreeMarker作为视图层组件,是为给如 Struts这样的 Model2框架提供现成的解决方案,已经在一定情况下提高页面的响应速度。

    2.FreeMaker的作用:页面静态化
    a)JavaEEWeb 开发存在的问题:动态网页技术创建的网页相率低,需要把这些动态网页转换成静态网页,节省程序运行时间
    b)是不是把一个系统中所有的网页都进行静态化?   什么样的页面需要静态化?
    [1]不是,因为当一个页面静态化之后,所有的写操作都会造成巨大的资源调动,造成更多资源的浪费,
    所以我们只将一些修改几率不大或不会修改的页面静态化。
    [2]例:电子图书、商品详情信息....
    c)CMS系统(Content Manager System)  就是把动态网页静态化

    d)页面静态化原理:

                

    3.FreeMaker的第一个程序:
    在pom文件中引入freemaker的插件,地址为:http://mvnrepository.com/artifact/org.freemarker/freemarker
    a)编码

    ftl(模板  由html标签和freemaker的表达式组成)

    <html>
        <body>
    	<h1>${name}</h1>
        </body>
    </html>

                    后台程序:

    //1 获取freemaker配置信息
    Configuration cfg = new Configuration("配置文件路径");//freemarker.template.Configuration;
    //2 作用这是ftl文件夹的位置
    cfg.setDirectoryForTemplateLoading(new File("文件夹路径"));
    //3 设置ftl文件的字符集编码
    cfg.setDefaultEncoding("UTF-8");
    //4 获取对应的使用模板
    Template temmplate = cfg.getTemplate("文件名.ftl");
    //5 设置模板中需要的动态数据  调用Service-----DAO
    Map root = new HashMap();
    root.put("name","yongqi_wang");
    //6 获取io流     输出     关流
    Writer out = new FileWriter(new File("静态网页生成后的存储路径路径/文件名.html"));
    template.process(root,out);
    out.flush();
    out.close();
    4.FreeMaker的模板书写
    a)单个数据的展示
    (1)零散变量:Map形式
    ${key}
    (2)对象形式: key.属性名
    ${user.id}
    ${user.name}

    b)有条件的展示数据 key == '值' / key.属性 == '值'

    <#if name=='yongqi_wang'>
        <h1>正确<h1>
    <#else>
        <h1>错误</h1>
    </#if>

            c)展示多个数据 

    /** List集合  user的创建过程省略假设拥有id和name两个属性
        List<User> users = ArrayList<User>();
        users.add(user);
        Map root = new HashMap();
        root.put("us",users);
    */
    <#list us as item>
        ${item.id}
        ${item.name}
    <#list>
    /**  Map集合
        Map m = new HashMap();
        m.put("name","yongqi_wang");
        Map root = new HashMap();
        root.put("mp",m);
    */
    <#list mp?keys as key>//判断map中是否存在key如果包含则将其命名为key
        ${mp[key]}
    </#list>

            d)日期类型的处理

    /**
        Map root = new HashMap();
        root.put("cdate",new Date());
    */
    ${cdate?date}//年月日
    ${cdate?datetime}//年月日时分秒
    ${cdate?time}//时分秒
    ${cdate?string('yyyy/MM/dd')}//指定日期格式

            e)null值的转换

    /**
        Map root = new HashMap();
        root.put("name",null);
    */
    ${name!'默认值'}//为空值添加默认值否则报错 可以给空串
    ///空值错误:Expression name is undeflnad on line............
    	
    空值的判断
    <#if name??>
        不是空的
    <#else>
        是空的
    </#if>

            f)<#include "其他页面路径">   //包含其他页面

    像其他的一些标量、容器什么的如果你了解过的话会发现它没什么特别的就是一个稍微不一样的称呼而已

    标量我们可以理解为java中的变量类型:String、数字类型(不区分整数和浮点数)、布尔值、日期类型这几种

    容器:

        哈希表:可以类比于java中的HashMap使用key-value形式存数元素是无序的

        序列:类似于java中的ArrayList,使用类似数组的实现方式通过下标存储但其中存储的元素类型可以不一致

        集: 从模板设计者角度来看,集是有限制的序列。不能获取集的大小,也不能通过 索引取出集中的子变量,但是它们仍然可以通过 list 指令来遍历。

    基本的语法就介绍到这里,如果你真的想了解更多关于FreeMarker的相关信息和深入原理,可以通过下面的网址来获取资源,也可以直接到FreeMarker官方自行查看。

    如果你觉得写的还不错,记得点个赞哟~!!!

    链接:https://pan.baidu.com/s/1wXUBDDDa2qouKgqPzHJtnQ          密码:msva

    下面是链接中手册的浏览目录内容


    展开全文
  • freemarker语法与介绍

    千次阅读 2018-02-26 19:00:29
    什么是freemarker FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于...
  • Freemarker条件判断

    万次阅读 2018-08-18 11:55:02
    判断语法 &lt;#if target??&gt; xxxx &lt;/#if&gt; 比如 判断索引,是否为偶数 &lt;#if student_index % 2 == 0&gt; xxxx &lt;#else&...//6....Map data ...
  • freeMarker读取布尔值,布尔值判断

    万次阅读 2018-07-12 16:55:06
    最近用到freeMarker, 也用到了布尔值,看到一篇文章中这样描述:在后台逻辑里,定义了布尔类型的变量 将该变量放进ModelMap model Boolean isAct = false; model.addAttribute("isACt", isAct); 在前端...
  • 博客分类: Java . FreeMarker中的<#if>标签除了里面直接判断 boolean...
  • freemarker #if 数值判断

    千次阅读 2020-03-03 15:35:41
    第一种情况是符合某个条件的时候,我们让显示中间的代码,假如下面这是当部门id是20的时候显示: <#if deptId==20> <input type="hidden" name="qc.supplierId" value="${(qc.supplierId)!...
  • freemarker if判断

    万次阅读 2018-08-31 17:47:19
    1.效果 &lt;div class="row cl"&gt;  &lt;label class="form-label col-xs-4 col-sm-2"&gt;类型:  &lt;#if name??&gt; //判断字符串是否为空 ...c-red&quo
  • Freemarker

    千次阅读 2019-09-09 23:21:06
    1. 什么是Freemarker 在java领域,表现层技术主要有三种:jsp、freemarker、velocity。 jsp是大家最熟悉的技术 优点: 1、功能强大,可以写java代码 2、支持jsp标签(jsp tag) 3、支持表达式语言(el) 4、官方...
  • freemarker实现和原理

    千次阅读 2015-11-17 13:03:26
    freemarker
  • freemarker类型转换

    千次阅读 多人点赞 2019-07-31 19:13:33
    操作字符串函数 1. substring(start,end)从一个字符串中截取子串 ...start:截取子串开始的索引,start必须大于等于0,小于等于end ...end: 截取子串的长度,end必须大于等于0,小于等于字符串长度,如果省略该...
  • freemarker

    2018-12-17 16:48:05
    freemarker freemarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,...
  • freemarker中的if...elseif...else语句

    万次阅读 2014-05-27 22:29:05
    freemarker中的if...elseif...else语句 1、设计示例 <#if student.studentAge lt 12> ${student.studentName}不是一个初中生 <#elseif student.studentAge lt 15> ${student.studentName}...
  • 安装freemarker插件(freemarker的eclipse插件) a) 首先下载 freemarker-ide-0.9.14.zip(在这里不用下载了,附件中已经有了) b) 解压后:把hudson.freemarker_ide_0.9.14这个文件放到:eclipse\plugins下面 c) 发现...
  • 浅谈jsp、freemarker、velocity区别

    万次阅读 多人点赞 2013-11-18 13:51:37
    以前做web开发页面层用的基本就是就是,最近公司java项目页面层用的技术是...在java领域,表现层技术主要有三种:jsp、freemarker、velocity。 jsp是大家最熟悉的技术 优点: 1、功能强大,可以写java代码 2、支持js
  • JavaEE进阶——FreeMarker模板引擎

    万次阅读 2018-07-18 15:32:50
    I. 简介 FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本...模板编写为FreeMarker Template Language (FTL)。 在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于...
  • springboot整合freemarker

    万次阅读 2017-06-28 17:02:00
    http://www.cnblogs.com/nannan0226/p/6400273.html http://412887952-qq-com.iteye.com/blog/2335218 前提: 开发工具:idea 框架:spring boot、maven 1、pom文件添加依赖 dependency> group
  • freemarker报错之十

    千次阅读 2014-06-03 22:32:55
    1、错误描述 freemarker Error on line 12, column 12 in list.ftl Expecting a string, date or number here, Expression num is instead a freemarker.core.NumericalRange The
1 2 3 4 5 ... 20
收藏数 71,126
精华内容 28,450
关键字:

freemarker