mpresslons le saunier中文

LetterMpress for Mac v1.4.0
苹果软件园官方微信号,求关注:
类似软件推荐
来自Mac App Store官方介绍
LetterMpress is a creative environment that lets you design beautiful compositions with vintage wood type and art cuts on a virtual hand-driven printing press.LetterMpress gives you the experience of producing your designs on a letterpress -- placing and arranging type on the press bed, inking, and then turning the hand crank to make a print.Every step in the printing process is replicated on the Mac, to give you an authentic, interactive experience.Try something new. Experiment. Have fun! You'll soon see why the art and craft of letterpress is becoming so popular.LetterMpress is easy to learn and fun to do, but it's not a toy. Create designs with authentic wood type and vintage "art cuts." You can mix custom colors and make multiple impressions on a single sheet. The specially designed studio environment lets you create and save several variations.Once you have created your prints you can print, copy, or export. The files can be opened or imported by most popular graphics applications, allowing you to integrate authentic wood type and art impressions into your design palette.With LetterMpress you can create: Fine art posters Event posters and mailers Invitations Music CD covers Greeting cards Scrapbook covers and interior pages Signage Calendars Framed wall art, and more…更多… v1.4.0版本新功能
Version 1.4.0: 5 additional typefaces: Caslon, Devinne, Fanfare, German Gothic, Hebrew Sans.Fanfare and German Gothic include German characters like eszett and standalone diacritics like acute, grave, circumflex, and umlaut.Hebrew Sans represents a complete basic set of the Hebrew alphabet.14 new pieces of art including linocuts created by artist Lisa Kesler.Fixed printing of ligature 'fi' in Bodoni Ultra.Fixed printing of 'Exclamation' in Bradley and Old Style…更多…
相关截图 图片数: 5 张(点击图片查看大图)
上一条:下一条:
下载列表 文件数: 1 文件大小:
& LetterMpress for Mac
苹果软件园官方微信号,专为大家推送苹果相关知识百科,求关注!
小编微信号,有关Mac问题不懂的欢迎扫码咨询,知无不言言无不尽^_^
MAC设计热门APPSMpress_程序加密壳 V2.17 绿色版 可执行程序压缩加密软件 - 偶要下载站
偶要下载站 / 绿色软件下载联盟站!为大家提供一手绿色软件下载服务!
当前位置: &
> Mpress_程序加密壳 V2.17 绿色版 可执行程序压缩加密软件
Mpress_程序加密壳 V2.17 绿色版 可执行程序压缩加密软件
查找了一下关于“Mpress”这款程序加密壳的资料,发现网络上基本没有,为什么呢?也许用它来加密程序的人不多吧,既然通用性不好,那么也决定了它所加密的程序不会被轻易的解密,至少除了高手之外,很难有人可以对其吧?非常不错的可执行程序压缩加密软件,已经汉化了!
界面预览图:
Mpress_程序加密壳 V2.17 绿色版 可执行程序压缩加密软件
如果看不到下载地址,请更换其他浏览器!
想下载到手机上? 鼠标移动到左边二维码上扫一扫即可!
1、如果发现下载地址不能下载,请多试几个下载地址!安装及使用时出现问题,安装方法与使用教程请到官方网站获取或搜索。
2、为了保证您享受到最快的下载速度,推荐安装迅雷下载工具。如果下载后出现不能解压,请安装winrar等解压缩包软件!
3、如果下载的压缩包文件需要解压密码,网址就是解压密码:www.ouyaoxiazai.com
4、本站不提供该下载软件的破解版,注册机,注册码,序列号,注册密钥,激活码,等相关信息下载以及咨询!
免费版/简体中文/★★★★☆
绿色版/简体中文/★★★☆☆
绿色版/简体中文/★★☆☆☆
汉化版/英文/★★★★☆
官方版/英文/★★★★☆
免费版/英文/★★☆☆☆
下载排行榜
人气下载榜
偶要下载站集绿色软件下载、手机软件与游戏、各种素材、字体下载于一身的联盟网站,致力打造一个纯绿色软件下载乐园。
本站为非营利性网站,中国绿色联盟提供的资源均来自网络收集整理,下载个人纯属学习交流之用,如有侵犯您的版权请与我联系,我们会马上改正请在下载24小时内删除!
Copyright &
偶要下载(OuyaoXiazai.Com) All Rights Reserved. 鲁ICP备号 鲁公网安备74号当前位置: >>
FreeMarker中文版文档
FreeMarker 手册用于 FreeMarker 2.3.18Translated By Nan Lei 南磊 译Copyright: The Chinese translation of the FreeMarker Manual by Nan Lei is licensed under a Creative Commons Attribution 3.0 Unported License (see http://creativecommons.org/licenses/by/3.0/ ). This licence only applies to the Chinese translation, not to the original (English) FreeMarker Manual. 版权说明: FreeMarker 中文版手册由南磊翻译,本文档基于 Creative Commons Attribution 3.0 Unported 授权许可(参见 http://creativecommons.org/licenses/by/3.0/deed.zh) 本许可仅应用于中文版,不对原版英文手册。 (译者联系方式为: 或 http://weibo.com/nanlei1987) 目录FreeMarker 手册 .......................................................................................................... 1 用于 FreeMarker 2.3.18 ........................................................................................... 1 目录................................................................................................................................. 2 前言................................................................................................................................. 7 什么是 FreeMarker? ................................................................................................. 7 我们应该阅读什么内容? .......................................................................................... 7 文档规约................................................................................................................... 8 联系我们................................................................................................................... 8 几点说明................................................................................................................... 8 第一部分 模板开发指南 ................................................................................................... 9 第一章 模板开发入门 ............................................................................................... 9 1.1 1.2 1.3 1.4 简介 ............................................................................................................ 9 模板 + 数据模型 = 输出 ............................................................................. 9 数据模型一览 ............................................................................................ 10 模板一览 ................................................................................................... 13第二章 数值和类型 ................................................................................................. 19 2.1 基本内容 ................................................................................................... 19 2.2 类型 .......................................................................................................... 21 第三章 模板 ........................................................................................................... 25 3.1 总体结构 ................................................................................................... 25 3.2 指令 .......................................................................................................... 26 3.3 表达式 ....................................................................................................... 27 3.4 插值 .......................................................................................................... 42 第四章 其它 ........................................................................................................... 45 4.1 自定义指令 ................................................................................................ 45 4.2 在模板中定义变量 ..................................................................................... 50 4.3 命名空间 ................................................................................................... 53 4.4 空白处理 ................................................................................................... 56 4.5 替换(方括号)语法................................................................................... 59 第二部分 程序开发指南 ................................................................................................. 61 第一章 程序开发入门 ............................................................................................. 61 1.1 创建配置实例 ............................................................................................ 61 1.2 创建数据模型 ............................................................................................ 61 1.3 获得模板 ................................................................................................... 62 1.4 合并模板和数据模型 .................................................................................. 63 1.5 将代码放在一起.......................................................................................... 63 第二章 数据模型 .................................................................................................... 65 2.1 基本内容 ................................................................................................... 65 2.2 标量 .......................................................................................................... 65 2.3 容器 .......................................................................................................... 66 2.4 方法 .......................................................................................................... 67 2.5 指令 .......................................................................................................... 68 2.6 节点变量 ................................................................................................... 74 2.7 对象包装 ................................................................................................... 75 第三章 配置 ........................................................................................................... 79 3.1 基本内容 ................................................................................................... 79 3.2 共享变量 ................................................................................................... 79 3.3 配置信息 ................................................................................................... 80 3.4 模板加载 ................................................................................................... 82 3.5 错误控制 ................................................................................................... 85 第四章 其它 ........................................................................................................... 89 4.1 变量 .......................................................................................................... 89 4.2 字符集问题 ................................................................................................ 89 4.3 多线程 ....................................................................................................... 91 4.4 Bean 的包装................................................................................................ 91 4.5 日志 .......................................................................................................... 97 4.6 在 Servlet 中使用 FreeMarker ...................................................................... 98 4.7 为 FreeMarker 配置安全策略......................................................................105 4.8 遗留的 XML 包装实现................................................................................106 4.9 和 Ant 一起使用 FreeMarker.......................................................................109 4.10 Jython 包装器 ..........................................................................................110 第三部分 XML 处理指南................................................................................................112 前言.......................................................................................................................112 第一章 揭示 XML 文档 ...........................................................................................113 1.1 节点树 ......................................................................................................113 1.2 将 XML 放到数据模型中 ............................................................................115 第二章 必要的 XML 处理........................................................................................117 2.1 通过例子来学习 ........................................................................................117 2.2 形式化描述 ...............................................................................................124 第三章 声明的 XML 处理........................................................................................129 3.1 基础内容 ..................................................................................................129 3.2 详细内容 ..................................................................................................131 第四部分 参考文档 .......................................................................................................134 第一章 内建函数参考文档 .....................................................................................134 1.1 处理字符串的内建函数 .............................................................................134 1.2 处理数字的内建函数 .................................................................................147 1.3 处理日期的内建函数 .................................................................................151 1.4 1.5 1.6 1.7 处理布尔值的内建函数 .............................................................................155 处理序列的内建函数 .................................................................................156 处理哈希表的内建函数 .............................................................................161 处理节点(XML)的内建函数....................................................................1621.8 很少使用的和专家级的内建函数 ...............................................................163 第二章 指令参考文档 ............................................................................................167 2.1 if,else,elseif 指令 ...................................................................................167 2.2 switch,case,default,break 指令..............................................................169 2.3 list,break 指令 .........................................................................................170 2.4 include 指令 ...............................................................................................171 2.5 import 指令 ...............................................................................................174 2.6 noparse 指令 ..............................................................................................175 2.7 compress 指令 ............................................................................................176 2.8 escape,noescape 指令...............................................................................177 2.9 assign 指令 ................................................................................................179 2.10 global 指令 ..............................................................................................181 2.11 local 指令 ................................................................................................182 2.12 setting 指令 .............................................................................................182 2.13 用户自定义指令(&@...&)......................................................................184 2.14 macro,nested,return 指令 ....................................................................186 2.15 function,return 指令...............................................................................190 2.16 flush 指令 ................................................................................................192 2.17 stop 指令.................................................................................................192 2.18 ftl 指令 ....................................................................................................193 2.19 t,lt,rt 指令 ..........................................................................................194 2.20 nt 指令 ....................................................................................................195 2.21 attempt,recover 指令 .............................................................................196 2.22 visit,recurse,fallback 指令 .....................................................................197 第三章 特殊变量参考文档 .....................................................................................202 第四章 FTL 中的保留名称.......................................................................................204 第五章 废弃的 FTL 结构 .........................................................................................205 5.1 废弃的指令列表 ........................................................................................205 5.2 废弃的内建函数列表 .................................................................................205 5.3 老式的 macro 和 call 指令 ..........................................................................205 5.4 转换指令 ..................................................................................................207 5.5 老式 FTL 语法............................................................................................208 5.6 #{…}式的数字插值 ......................................................................................209 第五部分 附录 ..............................................................................................................211 附录 A FAQ .............................................................................................................211 1. JSP 和 FreeMarker 的对比 .............................................................................211 2. Velocity 和 FreeMarker 的对比.......................................................................212 3. 为什么 FreeMarker 对 null-s 和不存在的变量很敏感,如何来处理它? ......212 4. 文档编写了特性 X,但是好像 FreeMarker 并不知道它,或者它的行为和文档描 述的不同,或者一个据称已经修改的 BUG 依然存在。.....................................213 5. 为什么 FreeMarker 打印奇怪的数字数字格式(比如 1,000,000 或 1 000 000 而不 是 1000000)? ...............................................................................................213 6. 为什么 FreeMarker 会打印不好的小数和/或分组分隔符号 (比如 3.14 而不是 3,14) .......................................................................................................................214 7. 为什么当我想用如格式打印布尔值时,FreeMarker 会抛出错误,又如何来修正 呢?................................................................................................................214 8. FreeMarker 标签中的&和&混淆了编辑器或 XML 处理器,应该怎么做? .........214 9. 什么是合法的变量名? ...............................................................................214 10. 如何使用包含空格,或其他特殊字符的变量(宏)名? ............................215 11. 当我试图使用 JSP 客户标签时为什么会得到非法参数异常:形式参数类型不匹 配?................................................................................................................215 12. 如何像 jsp:include 一样的方式引入其它的资源?................................216 13. 如 何 给 普 通 Java 方 法 / TemplateMethodModelEx/ TemplateTransformModel/ TemplateDirectiveModel 的 实现传 递普通 java.lang.* / java.util.*对象的参数? ...............................................216 14. 为什么在 myMap[myKey]表达式中不能使用非字符串的键?那现在应该怎么 做?................................................................................................................217 15. 当使用?keys/?values 遍历 Map(哈希表)的内容时,得到了混合真正 map 条目的 java.util.Map 的方法。当然,只是想获取 map 的条目。 ...............218 16. 在 FreeMarker 的模板中如何改变序列(lists)和哈希表(maps)? ...........218 17. 关于 null 在 FreeMarker 模板语言是什么样的? ......................................219 18. 我该怎么在表达式(作为另外一个指令参数)中使用指令(宏)的输出? 220 19. 在输出中为什么用“?”来代替字符 X? ..................................................220 20. 在模板执行完成后,怎么在模板中获取计算过的值? ................................221 21. 我能允许用户上传模板吗?又如何保证安全呢? .......................................221 22. 如何在 Java 语言中实现方法或宏而不是在模板语言中?............................222 23. 为什么 FreeMarker 的日志压制了我的应用程序? ......................................222 24. 在基于 Servlet 的应用程序中,如何在模板执行期间发生错误时,展示一个友 好的错误提示页面,而不是堆栈轨迹? ...........................................................223 25. 我正使用一个可视化的 HTML 割裂模板标记的编辑器。你们可以改变模板语言 的语法来兼容我的编辑器么? .........................................................................223 26. FreeMarker 有多快?真的是 2.X 版本的要比 1.X 版本 (经典的 FreeMarker) 的慢 吗?................................................................................................................223 27. 我的 Java 类怎么才能获取到关于模板结构的信息(比如所有变量的列表)? .......................................................................................................................224 28. 你会一直提供向后的兼容性吗? ...............................................................224 29. 如果我们把 FreeMarker 和我们的产品一起发行, 我们需要发布我们产品的源代 码么? ............................................................................................................225 附录 B 安装 FreeMarker..........................................................................................226 附录 C 构建 FreeMarker..........................................................................................227 附录 D 版本...........................................................................................................228 2.3.18 版 .........................................................................................................228 2.3.17 版 .........................................................................................................228 2.3.16 版.........................................................................................................231 2.3.15 2.3.14 2.3.13 2.3.12 版.........................................................................................................231 版.........................................................................................................232 版.........................................................................................................233 版.........................................................................................................2332.3.11 版.........................................................................................................234 2.3.10 版.........................................................................................................235 2.3.9 版 ..........................................................................................................236 2.3.8 版 ..........................................................................................................237 2.3.7 版 ..........................................................................................................237 2.3.7 RC1 版.....................................................................................................238 2.3.6 版 ..........................................................................................................239 2.3.5 版 ..........................................................................................................239 2.3.4 版 ..........................................................................................................240 2.3.3 版 ..........................................................................................................241 2.3.2 版 ..........................................................................................................242 2.3.1 版 ..........................................................................................................243 2.3 版 .............................................................................................................245 2.2.8 版 ..........................................................................................................258 2.2.7 版 ..........................................................................................................258 2.2.6 版 ..........................................................................................................258 2.2.5 版 ..........................................................................................................259 2.2.4 版 ..........................................................................................................260 2.2.3 版 ..........................................................................................................260 2.2.2 版 ..........................................................................................................261 2.2.1 版 ..........................................................................................................261 2.2 版 .............................................................................................................262 2.1.5 版 ..........................................................................................................270 2.1.4 版 ..........................................................................................................270 2.1.3 版 ..........................................................................................................270 2.1.2 版 ..........................................................................................................271 2.1.1 版 ..........................................................................................................271 2.1 版 .............................................................................................................272 2.01 版 ...........................................................................................................276 2.0 版 .............................................................................................................276 2.0 RC3 版........................................................................................................277 2.0 RC2 版........................................................................................................278 2.0 RC1 版........................................................................................................279 附录 E 许可 ...........................................................................................................282 词汇表 ..........................................................................................................................283 前言什么是 FreeMarker?FreeMarker 是一款模板引擎:一种基于模板的、用来生成输出文本(任何来自于 HTML 格式的文本用来自动生成源代码)的通用工具。它是为 Java 程序员提供的一个开发包或者说 是类库。 它不是面向最终用户, 而是为程序员提供的可以嵌入他们开发产品的一款应用程序。 FreeMarker 的设计实际上是被用来生成 HTML 网页, 尤其是通过基于实现了 MVC(Model View Controller, 模型-视图-控制器)模式的 Servlet 应用程序。 使用 MVC 模式的动态网页的构 思使得你可以将前端设计者(编写 HTML)从程序员中分离出来。所有人各司其职,发挥其擅 长的一面。 网页设计师可以改写页面的显示效果而不受程序员编译代码的影响, 因为应用程 序的逻辑(Java 程序)和页面设计(FreeMarker 模板)已经分开了。页面模板代码不会受到复杂 的程序代码影响。 这种分离的思想即便对一个程序员和页面设计师是同一个人的项目来说都 是非常有用的,因为分离使得代码保持简洁而且便于维护。 尽管 FreeMarker 也有编程能力, 但它也不是像 PHP 那样的一种全面的编程语言。 反而, Java 程序准备的数据来显示(比如 SQL 查询),FreeMarker 仅仅使用模板生成文本页面来呈现 已经准备好的数据。FreeMarker 不是 Web 应用框架。它是 Web 应用框架中的一个适用的组件,但是 FreeMarker 引擎本身并不知道 HTTP 协议或 Servlet。它仅仅来生成文本。即便这样,它也非 常适用于非 Web 应用环境的开发。要注意的是,我们使用 FreeMarker 作为视图层组件,是 为给如 Struts 这样的 Model 2 框架提供现成的解决方案。 FreeMarker 是免费的,基于 BSD 规则的许可。它是 OSI 认证的开源软件。OSI 认证是开 源倡议的认证标识。我们应该阅读什么内容?如果你是一名… 前端设计师, 那么你应该阅读模板开发指南, 然后如果需要的话可以阅读参考手册来获 取更多技术细节。 程序员,那么你应该先阅读模板开发指南,然后是程序开发指南,最后如果需要的话可 以阅读参考手册来获取更多技术细节。 文档规约变量名,模板代码段,Java 类名等用如下格式书写,如:foo 。 如果需要具体值来代替某些内容,那么用斜体书写,如:Hello yourName! 模板示例如下书写: Something 数据对象示例如下书写: Something 输出数据示例如下书写: Something 程序示例如下书写: Something 在面向页面设计师和程序员所编写的章节中代码段给程序员这样写: 这只是对程序员而 言的。 这样来强调新名词:一些新名词联系我们获取最新版本的 FreeMarker,订阅邮件请访问 FreeMarker 主页:http://freemarker.org 如果你需要帮助或者有好的建议, 可以使用邮件(邮件文件可以免费搜索)或者 Web 论坛。 如果你想报告一个 Bug,请使用 Web 的 Bug 跟踪系统或者是邮件。查阅这些内容请访问 http://freemarker.org。同时,要注意我们有一个 FAQ 和索引,你可以使用它们。几点说明因为英文版文档的作者是匈牙利人,其母语非英语,那么在这种情况的翻译过程,可能 会有错误存在,作者结合自身多年对 FreeMarker 的实践力求精准,但因个人才疏学浅,水 平有限,恳请读者批评指正。 手册的更新根据大家的反馈随时进行, 但只在有阶段性成果时公开发布修正版本, 并在 FreeMarker 2.4 版本研发完整后,会及时联系原作者获取新特性以便修改。 本翻译是免费的,您可以自由下载和传播,不可用于任何商业行为。但文档版权归译者 所有,原版归 FreeMarker 项目组所有,您可以引用其中的描述,但必须指明出处。如需用 于商业行为,您必须和原作者取得联系。 如果你发现英文原版任何错误(包括语法错误,错别字)或者是在文档中找到一些误导 或混淆错误,也可以是其他的建议,或是咨询 FreeMarker 中的问题,您可以联系原作者。 E-mail:ddekany@freemail.hu 关于本文档的翻译错误(包括语法错误,错别字)或中文技术交流,可以联系译者:
或 http://weibo.com/nanlei1987,我们共同研究,共同进步。 第一部分 模板开发指南第一章 模板开发入门 1.1 简介本章是关于 FreeMarker 非常简略的介绍, 后续章节中将会详细介绍它们。 不过没关系, 只要你阅读了本章节的内容,你就能够编写简单但却很有用的 FreeMarker 模板程序。1.2 模板 + 数据模型 = 输出假设你在一个在线商店的应用系统中需要一个 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&比方说,用户名(所有的”Big Joe”)应该是登录这个网页访问者的名字,最新产品的数 据应该来自于数据库,这样它才可以随时更新。在这样的情况下你不能在 HTML 页面中直接 输入登录的用户名,最新产品的 URL 和名称,你不能使用静态的 HTML 代码,那样是不能即 时改变的。 对于这个问题,FreeMarker 的解决方案是使用模板来代替静态 HTML 文本。模板文件同 样是静态的 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 服务器端的文件)在这个过程中也不会改变什么,所以这个转换过程发生在一次又一 次的访问中。这样就保证了显示的信息总是即时的。 现在,你也许已经注意到,该模板并没有包含关于如何找出当前的访问者是谁,或者是 如何去查询数据库查找最新的产品的指令。它似乎已经知道了这些数据。确实是这样, FreeMarker 背后(确切的说是 MVC 模式的背后)的重要思想就是表现逻辑和业务逻辑相分 离。在模板只是处理显示问题,也就是视觉设计问题和格式问题。所准备要显示的数据(如 用户名等)与 FreeMarker 无关,这通常是使用 Java 语言或其他目的语言来编写的。所以模 板开发者不需要关心这些数值是如何计算出来的。事实上,在模板保持不变的同时,这些数 值的计算方式可以完全发生变化。而且,除了模板外,页面外观发生的变化可以完全不触碰 其他任何东西。 当模板开发者和程序员是不同一个人的时候, 分离带来的好处更是显而易见 的。 FreeMarker(还有模板开发者)并不关心数据是如何计算的,FreeMarker 只是知道真实 的数据是什么。模板能用的所有数据被包装成 data-model 数据模型。数据模型的创建是通 过已经存在的程序计算得到的。至于模板开发者,数据模型像是树状结构(比如硬盘上的文 件夹和文件) ,正如本例中的数据模型,就可以如下形式来描述:(root) | +- user = &Big Joe& | +- latestProduct | +- url = &products/greenmouse.html& | +- name = &green mouse&(为了避免误解:数据模型并不是文本文件,上面所描述的只是一种数据模型的表现形式。 它来自于 Java 对象,但这会成为 Java 程序员要面对的问题。 ) 比较之前你在模板中看到的${user} 和${latestProduct.name} 。作为一种 比喻:数据模型就像计算机文件系统上的内容:根 root 和 latestProduct 对应目录 (文件夹) user , , url 和 name 对应文件。url 和 name 在 latestProduct 目录 中,所以 latestProduct.name 就像是说 latestProduct 目录的 name 一样。 但是我所说的,这仅仅是个比喻,这里并没有真实的文件和目录。 概括地讲,模板和数据模型是 FreeMarker 所需,并用来生成输出内容的(比如之前展 示的 HTML) :模板+数据模型=输出1.3 数据模型一览正如你看到的, 数据模型基本结构是树状的。 这棵树可以复杂而且有很大的深度, 比如: (root) | +- animals | | | +- mouse | | | | | +- size = &small& | | | | | +- price = 50 | | | +- elephant | | | | | +- size = &large& | | | | | +- price = 5000 | | | +- python | | | +- size = &medium& | | | +- price = 4999 | +- test = &It is a test& | +- whatnot | +- because = &don't know&上图中变量扮演目录的角色 (根 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 就是序列: (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&可以使用数组的方括号方式来访问一个序列的子变量。 索引从零开始 (从零开始是程序 员写代码的传统习惯) ,那么就意味着序列第一项的索引是 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,译者注)的子变量,这个变量存储这个动物是否被保护起来。 总结: 数据模型可以被看做是树状结构的。 标量存储单一的值,这种类型的值可以是字符串,数字,日期/时间或者是布尔值。 哈希表是存储变量和与其相关且有唯一标识名称变量的容器。 序列是存储有序变量的容器。 存储的变量可以通过数字索引来检索, 索引通常从零开始。1.4 模板一览1.4.1 简介最简单的模板是普通 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 标签”和“指令”看做是同义词即可。 )1.4.2 指令示例尽管 FreeMarker 有很多指令,作为入门,在快速了解过程中我们仅仅来看三个最为常 用的指令。 1.4.2.1 if 指令使用 if 指令可以有条件地跳过模板的一部分,这和程序语言中 if 是相似的。假设在第 一个示例中,你只想向你的老板 Big Joe(而不是其他人)问好,就可以这样做:&html& &head& &title&Welcome!&/title& &/head& &body& &h1& Welcome ${user}&#if user == &Big Joe&&, our beloved leader&/#if&! &/h1& &p&Our latest product: &a href=&${latestProduct.url}&&${latestProduct.name}&/a&! &/body& &/html&在这里, 我们告诉 FreeMarker, 我们尊敬的领导才是 if 条件中那唯一的 user 变量值, 当它和”Big Joe ”相同时才显示出来。那么,当 condition 的判断结果为 false(布尔 值)时,在&#if condition& 和&/#if& 标签之间的内容将会被略过。 我们来详细说说 condition 的使用:==是来判断在它两侧的值相等的操作符,比较的结 果是布尔值,true 或者 false。在== 的左侧,是引用的变量,我们很熟悉这样的语法,它会 被变量的值来替代。右侧是指定的字符串,在模板中的字符串必须放在引号内。 当 price 是 0 的时候,下面的代码将会打印:”Pythons are free today!”&#if animals.python.price == 0& Pythons are free today! &/#if&和前面的示例相似,字符串被直接指定,但是这里则是数字(0)被直接指定。注意到 数字是不用放在引号内的。如果将 0 放在引号内(”0”) ,FreeMarker 就会将其误判为字符 串了。 当 price 不是 0 的时候,下面的代码将会打印:”Pythons are not free today!”&#if animals.python.price != 0& Pythons are free today! &/#if&你也许会猜测了,!= 就是不等于。 你也可以这样来写代码(使用数据模型来描述哈希表变量) :&#if animals.python.price & animals.elephant.price& Pythons are cheaper than elephants today. &/#if& 使用&#else&标签可以指定当条件为假时程序执行的内容。例如:&#if animals.python.price & animals.elephant.price& Pythons are cheaper than elephants today. &#else& Pythons are not cheaper than elephants today. &/#if&如果蟒蛇的价格比大象的价格低,将会打印”Python are cheaper than elephants today.”, 否则就打印”Pythons are not cheaper than elephants today.” 如果变量本身就是布尔值(true 或者 false) ,那么可以直接让其作为 if 的条件 condition :&#if animals.python.protected& Warning! Pythons are protected animals! &/#if&1.4.2.2 list 指令当需要用列表来遍历集合的内容时,list 指令是非常好用的。例如,如果在模板中用前 面示例描述序列的数据模型。&p&We have these animals: &table border=1& &tr&&th&Name&th&Price &#list animals as being& &tr&&td&${being.name}&td&${being.price} Euros &/#list& &/table&那么输出结果将会是这样的:&p&We have these animals: &table border=1& &tr&&th&Name&th&Price &tr&&td&mouse&td&50 Euros &tr&&td&elephant&td&5000 Euros &tr&&td&python&td&4999 Euros &/table&list 指令的一般格式为: &#list sequence as loopVariable&repeatThis&/#list& repeatThis 部分将会在给定的 sequence 遍历时在每项中重复, 从第一项开始, 一个接着一个。在所有的重复中,loopVariable 将持有当前项的值。这个循环变量仅 存在于&#list …&和&/#list& 标签之间。再看一个示例,遍历示例数据模型 fruits。 &p&And BTW we have these fruits: &ul& &#list whatnot.fruits as fruit& &li&${fruit} &/#list& &ul&whatnot.fruits 表达式应该很熟悉了,我们引用了数据模型章节中示例的变量。1.4.2.3 include 指令使用 include 指令,我们可以在当前的模板中插入其他文件的内容。 假设要在一些页面中显示版权声明的信息。 那么可以创建一个文件来单独包含版权声明, 之后在 需要 它的地 方插 入即 可。比 方说 ,我 们可以 将版 权信 息单独 存放 在页 面文件 copyright_footer.html 中。&hr& &i& Copyright (c) 2000 &a href=&http://www.acmee.com&&Acmee Inc&/a&, &br& All Rights Reserved. &/i&当需要用到这个文件时,可以使用 include 指令来实现插入。&html& &head& &title&Test page&/title& &/head& &body& &h1&Test page&/h1& &p&Blah blah... &#include &/copyright_footer.html&& &/body& &/html&输出的内容为: &html& &head& &title&Test page&/title& &/head& &body& &h1&Test page&/h1& &p&Blah blah... &hr& &i& Copyright (c) 2000 &a href=&http://www.acmee.com&&Acmee Inc&/a&, 如果改变了 copyright_footer.html 中的内容, 那么访问者就会在所有页面中 &br& All Rights Reserved. &/i& &/body& 看到新的版权声明信息了。 &/html&1.4.2.4 联合使用指令在页面也可以多次使用指令,而且指令间可以相互嵌套,正如在 HTML 元素中嵌套使用 标签一样。下面的代码会遍历动物集合,用大号字体来打印大型动物的名字。&p&We have these animals: &table border=1& &tr&&th&Name&th&Price &#list animals as being& &tr& &td& &#if being.size == &large&&&font size=&+1&&&/#if& ${being.name} &#if being.size == &large&&&/font&&/#if& &td&${being.price} Euros &/#list& &/table&注意到 FreeMarker 并不解析 FTL 标签外的文本,插值和注释,当条件不满足时它也会 忽略所有嵌套的 font 标签。1.4.2.5 处理不存在的变量在实际应用中数据模型经常会有可选的变量(也就是说有时可能不存在实际值) 。除了 一些典型的人为原因导致失误, FreeMarker 不能容忍引用不存在的变量, 除非明确地告诉它 当变量不存在时如何处理。这里介绍两种典型的处理方法。这部分对程序员而言:一个不存在的变量和一个是 null 的变量,对于 FreeMarker 来 说是一样的,所以这里所指的丢失包含这两种情况。不论在哪里引用变量, 都可以指定一个默认值来避免变量丢失这种情况, 通过在变量名 后面跟着一个!和默认值。就像下面的例子,当 user 从数据模型中丢失时,模板将会将 user 的值表示为字符串”Anonymous”。 (若 user 并没有丢失,那么模板就会表现 出”Anonymous”不存在一样) :&h1&Welcome ${user!&Anonymous&}!&/h1&当然也可以在变量名后面通过放置?? 来询问 FreeMarker 一个变量是否存在。将它和 if 指令合并,那么如果 user 变量不存在的话将会忽略整个问候代码段:&#if user??&&h1&Welcome ${user}!&/h1&&/#if&关 于 多 级 访 问 的 变 量 , 比 如 animals.python.price , 书 写 代 码 :animals.python.price!0 ,仅当 animals.python 存在而仅仅最后一个子变 量 price 可能不存在(这种情况下我们假设价格是 0) 。如果 animals 或者 python不存在, 那么模板处理过程将会以 “未定义的变量” 错误而停止。 为了防止这种情况的发生, 可以这样来书写代码(animals.python.price)!0 。这种情况下当 animals 或python 不存在时表达式的结果仍然是 0。对于??也是同样用来的处理这种逻辑的: animals.python.price?? 对比(animals.python.price)?? 来看。 第二章 数值和类型 2.1 基本内容2.1.1 简介注意: 这里假设你已经阅读完入门章节的内容了。 理解数值和类型的概念是理解数据模型的关键和基础。 然而, 数值和类型的概念并不局 限于数据模型,下面你就会看到了。2.1.2 什么是数值?这部分对于程序员来说可以直接跳过这,它和程序语言中的数值类型是相似的。你所知道的来自于每天所使用的数字,比如 16,0.5 等这些用语就是数值的示例,也就 是数字。在计算机语言中,这些用语有着更广泛的含义,比如数值并不一定是数字值,看下 面这个数据模型:(root) | +- user = &Big Joe& | +- today = Jul 6, 2007 | +- todayHoliday = false | +- lotteryNumbers | | | +- (1st) = 20 | | | +- (2st) = 14 | | | +- (3rd) = 42 | | | +- (4th) = 8 | | | +- (5th) = 15 | +- cargo | +- name = &coal& | +- weight = 40 我们说变量 user 的数值是”Big Joe”(字符串) today 的数值是 Jul 6,2007(日期) , , todayHoilday 的数值是 false(布尔值,是/否,这样的值) lotteryNumbers 的 。 数值是包含 20,14,42,8,15 的序列。在这种意义上,lotteryNumbers 是多值的, 它包含多个数值(如其中的第二项是 14) ,但是 lotteryNumbers 本身还是单值。它像 一个装有很多东西的盒子,整个盒子被看做是独立的。最后有一个数值 cargo ,它是一个 哈希表(也可以看做是盒子) 。所以数值就是存储在变量中的(在 user , cargo 或 cargo.name 中) 东西。 但是不需要存储的数值也可以称之为数值, 比如这里的数字 100: &#if cargo.weight & 100&Light cargo&/#if& 当模板被执行时,计算的临时结果也称为数值,比如 20+120(它会打印 120) : ${cargo.weight / 2 + 100} 这最后一种的解释:两个数 40(货物的重量)和 2 相除的结果是 20,这是一个新计算 出的数值。把它和 100 相加,那么 120 就出来了,接着就打印出来了(${…} ) ,接着模板 继续向下执行直到所有结果都计算出来。 现在你应该能体会到数值这个词的含义了,不仅仅是数字的值。2.1.3 什么是类型?数值中非常重 要的一个 概念就是 类型。比 方说,变 量 user 的类型是字符串,lotteryNumbers 的类型是序列。数值的类型非常重要,因为它决定了这些数值可以在 哪里使用的最大限度。比如${user/2} 就是错误的,但是${cargo.weight/2} 就能 计算出结果 20,除法仅对数字值有效,而不能作用于字符串。仅当 cargo 是一个哈希表 时 cargo.name 可以使用。也可以用&#list …&仅仅来遍历序列。&#if …& 指令的 条件 condition 只能是布尔值等。注意: 这里说一点点术语:称 “布尔”或“布尔值”或“布尔类型”都是相同的含义。 数值同时也可以含有多种类型,尽管这样很少使用。看下面这个数据模型 mouse ,就 又是字符串又是哈希表。(root) | +- mouse = &Yerri& | +- age = 12 | +- color = &brown&如果用上面的数据模型合并到模板中,就该这么来写:${mouse} &#-- 用 mouse 作为字符串 --& ${mouse.age} &#-- 用 mouse 作为哈希表 --& ${mouse.color} &#-- 用 mouse 作为哈希表 --&它的输出内容为: Yerri 12 brown2.1.4 数据模型是哈希表注意观察每个你已经知道的数据模型:被”(root)”标识的内容就是哈希表类型的数值。 当书写如 user 这样的代码,那就意味着想要把”user”变量存储在哈希表的根上。而如果代 码是:root.user ,也没有名为”root ”的变量,那么这就没有任何作用。 某些人也许会被这种数据模型的例子所困惑, 也就是说, 根哈希表包含更多的哈希表或 序列(如 lotteryNumbers 和 cargo) 。其他就没有更特殊的了。哈希表包含其他变量,那些变 量包含数值,数值可以是字符串,数字等,当然也可以是哈希表或序列。最初我们解释过, 就像字符串和数字,序列或哈希表也是数值。2.2 类型2.2.1 简介支持的类型有: ? 标量: ? ? ? ? ? ? ? ? 字符串 数字 布尔值 日期 哈希表 序列容器:? 集 子程序: ? 方法和函数 ? 用户自定义指令 其它/很少使用: ? 节点?2.2.2 标量标量是最基本,最简单的数值类型,它们可以是: ? 字符串:简单的文本,例如:产品的名称。 如果想在模板中直接给出字符串的值, 而不是使用数据模型中的变量, 那么将文本 写在引号内即可,比如”green mouse” 或者’green mouse’。 (关于语法 ?的更多细节请看后续章节) 数字:例如:产品的价格。整数和非整数是不区分的,只有单一的数字类型。比如使用了计算器,计算 3/2 的结果是 1.5 而不是 1。如果要在模板中直接给出数字的值, 可以这么来写: 150, -90.05, 或者 0.001 。 (关于语法的更多细节请看后续章节) ? 布尔值:布尔值代表了逻辑上的对或错(是或否) 。例如:用户到底是否登录了。 典型的应用是使用布尔值作为 if 指令的条件, 比如&#if loggedIn&…&/#if& 或者&#if price==0&…&/#if& ,后面这个 price==0 部分的结果就是布 尔值。 ? 在模板中可以使用保留字 true 和 false 来指定布尔值。 日期:日期变量可以存储和日期/时间相关的数据。一共有三种变化。 ? ? ? 精确到天的日期(通常指的是“日期”,比如 April 4, 2003 ) 每天的时间(不包括日期部分) ,比如 10:19:18 PM。时间的存储精确到毫秒。 日期-时间(也称作“时间戳”,比如 April 4, :18 PM。时间部分的 )存储精确到毫秒。 不幸的是,受到 Java 平台的限制,FreeMarker 是不能决定日期的部哪分来使用(也就 是说,是日期-时间格式,每天的时间格式等) 。这个问题的解决方法是高级主题了,后面的 章节将会讨论到。 在模板中直接定义日期数值是可以的,但这也是高级主题,后面的章节将会讨论到。 要记住,FreeMarker 区别字符串,数字和布尔值,所以字符串”150”和数字 150 是完全 不同的两种数值。数字持有的是数字的值,布尔值表达的是逻辑上的对或错。字符串可以是 任意字符的序列。2.2.3 容器这些值存在的目的是为了包含其他变量, 它们仅仅作为容器。 被包含的变量通常是子变 量。容器的类型有: ? 哈希表: 每个子变量都可以通过一个唯一的名称来查找, 这个名称是不受限制的字 符串。哈希表并不确定其中子变量的顺序,也就是说没有第一个变量,第二个变量 这样的说法, 变量仅仅是通过名称来访问的。 (就像 Java 语言中的 HashMap 一样, 是实现了 Hash 算法的 Map,不记录内部元素的顺序,仅仅通过名称来访问。译者 注) ? 序列: 每个子变量通过一个整数来标识。 第一个子变量的标识符是 0, 第二个是 1, 第三个是 2,这样来类推,而且子变量是有顺序的。这些数字通常被称为是子变量 的索引。序列通常比较密集,也就是所有的索引,包括最后一个子变量的,它们和 子变量都是相关联的, 但不是绝对必要的。 子变量的数值类型也并不需要完全一致。 集: 从模板设计者角度来看,集是有限制的序列。不能获取集的大小,也不能通过?索引取出集中的子变量,但是它们仍然可以通过 list 指令来遍历。 要注意一个数值也可有多种类型, 对于一个数值可能存在哈希表和序列这两种类型, 这 时, 该变量就支持索引和名称两种访问方式。 不过容器基本是当作哈希表或者序列来使用的, 而不是两者同时使用。 尽管存储在哈希表, (集) 序列 中的变量可以是任意类型的, 这些变量也可以是哈希表, 序列(集) 。这样就可以构建任意深度的数据结构。 数据模型本身(最好说成是它的根)也是哈希表。2.2.4 子程序 2.2.4.1 方法和函数一个值是方法或函数的时候那么它就可以计算其他值,结果取决于传递给它的参数。这部分是对程序员来说的:方法/ 函数是第一类值,就像函数化的编程语言。也就是说 函数/方法也可以是其他函数或方法的参数或者返回值,并可以把它们定义成变量。假设程序员在数据模型中放置了一个方法变量 avg ,那么它就可以被用来计算数字的 平均值。给定 3 和 5 作为参数,访问 avg 时就能得到结果 4。 方法的使用后续章节会有解释,下面这个示例会帮助我们理解方法的使用:The average of 3 and 5 is: ${avg(3, 5)} The average of 6 and 10 and 20 is: ${avg(6, 10, 20)} The average of the price of a python and an elephant is: ${avg(animals.python.price, animals.elephant.price)}可以得到如下的输出:The average of 3 and 5 is: 4 The average of 6 and 10 and 20 is: 12 The average of the price of a python and an elephant is: 4999.5那么方法和函数有什么区别呢?这是模板作者所关心的, 它们没有关系, 但也不是一点 关系都没有。方法是来自于数据模型(它们反射了 Java 对象的方法) ,而函数是定义在模板 内的(使用了函数指令-这也是高级主题) ,但二者可以用同一种方式来使用。2.2.4.2 用户自定义指令用户自定义指令 (换句话说, 就是 FreeMarker 的标签) 这种类型的值也是一种子程序, 一种可以复用的模板代码段。但这也是高级主题,我们在后续章节中会详细解释。这部分是对程序员来说的:用户自定义指令(比如宏) ,也是第一类值,就像函数/方法 一样。这里仅仅对用户自定义指令有一个认识即可(如果现在还不能理解可以先忽略它) 。假 设现在有一个变量,box ,它的值是用户自定义的指令,用来打印一些特定的 HTML 信息, 这个指令定义了一个标题和其中的信息。&@box title=&Attention!&& Too much copy-pasting may leads to maintenance headaches. &/@box& 2.2.4.3 函数/方法和用户自定义指令的比较这部分内容也是对高级用户来说的(如果你还不能理解可以先忽略它) 。如果要使用函 数/方法或自定义指令去实现一些东西的时候,二者之间的选择是两难的。按经验来说, 如果能够实现,请先用自定义指令而不要用函数/方法。指令的特征如下: ? 输出(返回值)的是标记(HTML,XML 等) 。主要原因是函数的返回结果可以自动 进行 XML 转义(这是因为${…}的特性) ,而用户自定义指令的输出则不是(这是 因为&@...& 的特性所致,它的输出假定为是标记,因此就不再转义) 。 ? 副作用也是很重要的一点, 它没有返回值。 例如一个指令的目的是往服务器日志中 添加一个条目。 (事实上你不能得到自定义指令的返回值,但有些反馈的类型是有 可能设置非本地变量的) 会进行流程的控制(就像 list 或 if 指令那样) ,但是不能在函数/方法上这么做。?在模板中,FreeMarker 不知道的 Java 对象的方法通常是可以作为方法来使用的,而不 用考虑 Java 对象方法本身的特性,因为在这里没有其他的选择。2.2.5 其它 2.2.5.1 节点节点变量代表了树状结构中的一个节点,而且通常是配合 XML 格式来处理的,这是专 业而且更高级的主题。 这里我们仅对高级用户进行一个概要说明: 节点和存储在其他节点中的序列很相似, 通 常也被当作为子节点。节点存储它所在的容器节点的引用,也就是父节点。节点的主要作用 是拓扑信息。 其它数据必须通过使用多类型的值来存储。 就像一个值可以同时是一个节点和 一个数字,这样它存储的数字可以作为如支付额来使用。除了拓扑信息,节点也可以存储一 些元信息(即 metadata,译者注) :如节点名称,它的类型(字符串) ,命名空间(作为字 符串) 。若一个节点象征 XHTML 文档中的 h1 元素,那么它的名字可以是”h1” ,类型可以 是”element”,命名空间可以是”http://www.w3.org/1999/xhtml”。但对于 数据模型设计者来说,这些元信息,还有如何来使用它们又有什么意义呢。检索拓扑信息和 元信息的方法将会在后续章节中来说明(这里你可以先不用理解它们) 。 第三章 模板注意: 这里假设你已经阅读完入门章节,数值和类型章节两部分了。3.1 总体结构实际上你用程序语言编写的程序就是模板,模板也被称为 FTL(代表 FreeMarker 模板语 言) 。这是为编写模板设计的非常简单的编程语言。 模板(FTL 编程)是由如下部分混合而成的: Text 文本:文本会照着原样来输出。 Interpolation 插值:这部分的输出会被计算的值来替换。插值由${ 和}所分隔(或者 #{和},这种风格已经不建议再使用了) 。 FTL tags 标签:FTL 标签和 HTML 标签很相似,但是它们却是给 FreeMarker 的指示,而 且不会打印在输出内容中。 Comments 注释: 的注释和 HTML 的注释也很相似, FTL 但它们是由&#-- 和--& 来分隔 的。注释会被 FreeMarker 所忽略,更不会在输出内容中显示。 我们来看一个具体的模板, 其中的内容已经用颜色来标记了: 文本,插值, FTL 标签,注释,为了看到可见的换行符,这里使用了[BR]。 &html&[BR] &head&[BR] &title&Welcome!&/title&[BR] &/head&[BR] &body&[BR] &#-- Greet the user with his/her name --&[BR] &h1&Welcome ${user}!&/h1&[BR] &p&We have these animals:[BR] &ul&[BR] &#list animals as being&[BR] &li&${being.name} for ${being.price} Euros[BR] &/#list&[BR] &/ul&[BR] &/body&[BR]&/html&FTL 是区分大小写的。list 是指令的名称而 List 就不是,类似地${name} 和 ${Name} 或者${NAME} 它们也是不同的。 应该意识到非常重要的一点:插值仅仅可以在文本中间使用(也可以在字符串表达式 中,后续将会介绍) 。FTL 标签不可以在其他 FTL 标签和插值中使用。下面这样写就是错的:&#if &#include 'foo'&='bar'&...&/#if&注释可以放在 FTL 标签和插值中间。比如: &h1&Welcome ${user &#-- The name of user --&}!&/h1&[BR] &p&We have these animals:[BR] &ul&[BR] &#list &#-- some comment... --& animals as &#-- again... --& being&[BR] ...注意: 如果目前您已经自己尝试了上面所有的示例的话, 那么你也许会注意一些空格、 制表符 和换行符从模板输出中都不见了, 尽管我们之前已经说了文本是按照原样输出的。 现在不用 为此而计较,这是由于 FreeMarker 的“空格剥离”特性在起作用,它当然会自动去除一些 多余的空格,制表符和换行符了。这个特性后续也会解释到。3.2 指令使用 FTL 标签来调用 directives 指令,比如调用 list 指令。在语法上我们使用了两个标 签:&#list animals as being& 和&/#list& 。 标签分为两种: ? 开始标签:&#directivename parametes& ? 结束标签:&/#directivename& 除了标签以#开头外,其他都和 HTML,XML 的语法很相似。如果标签没有嵌套内容(在 开 始 标 签 和 结 束 标 签 之 内 的 内 容 ) 那 么 可 以 只 使 用 开 始 标 签 。 例 如 &#if , something&...&/#if& , 但是 FreeMarker 知 道 &#include something& 中include 指令没有可嵌套的内容。 parameters 的格式由 directivename 来决定。事实上,指令有两种类型:预定义指令和用户自定义指令。对于用户自定义的指令使用@来代替#,比如&@mydirective parameters&...&/@mydirective& 。更深 的 区 别 在 于 如 果 指 令 没 有 嵌 套 内 容 , 那 么 必 须 这 么 使 用 &@mydirective parameters /&,这和 XML 语法很相似(例如&img ... /&).但是用户自定义指令是后面要讨论的高级主题。 像 HTML 标签一样,FTL 标签必须正确的嵌套使用。下面这段示例代码就是错的,因为 if 指令在 list 指令嵌套内容的内外都有:&ul& &#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&注意一下 FreeMarker 仅仅关心 FTL 标签的嵌套而不关心 HTML 标签的嵌套,它只会把 HTML 看做是相同的文本,不会来解释 HTML。 如果你尝试使用一个不存在的指令(比如你输错了指令的名称) ,FreeMarker 就会拒绝 执行模板,同时抛出错误信息。 FreeMarker 会忽略 FTL 标签中的多余空白标记,所以你也可以这么来写代码:&#list[BR] animals as[BR] being[BR] &[BR] ${being.name} for ${being.price} Euros[BR] &/#list &当然,也不能在& ,&/ 和指令名中间插入空白标记。 指令列表和详细介绍可以参考指令参考部分(但是我建议先看表达式章节) 。 注意: 通过配置, FreeMarker 可以在 FTL 标签和 FTL 注释中, 使用[和] 来代替& 和& , [#if 就像 user == &Big Joe&]...[/#if] 。要获取更多信息,请参考:第四章的其它/替换 (方括号)语法部分。 注意: 通过配置,FreeMarker 可以不需要#来理解预定义指令(比如&if user == &Big Joe&&...&/if& ) 。而我们不建议这样来使用。要获取更多信息,请参考:参考文档部 分,废弃的 FTL 结构/老式 FTL 语法。3.3 表达式3.3.1 简介当需要给插值或者指令参数提供值时,可以使用变量或其他复杂的表达式。例如,我们 设 x 为 8,y 为 5,那么(x+y)/2 的值就会被处理成数字类型的值 6.5 在我们展开细节之前,先来看一些具体的例子: ? 当给插值提供值时: 插值的使用方式为${expression}, 把它放到你想输出文 本的位置上然后给值就可以打印了。 ${(5+8)/2} 会打印”6.5”出来 即 (如果输出 的语言不是英语,也可能打印出”6,5”) 。 当给指令参数提供值时: 在入门章节我们已经看到 if 指令的使用了。 这个指令的语 法是:&#if expression&...&/#if& 。这里的表达式计算结果必须是布 尔类型的。比如&#if 2 & 3& 中的 2 & 3 (2 小于 3)是结果为 true 的布尔 表达式。?3.3.2 快速浏览(备忘单)这里是给已经了解 FreeMarker 的人或有经验的程序员的一个提醒: ? 直接指定值 ? 字 符 串 : &Foo& 或 者 'Foo' 或 者 &It's \&quoted\&& 或 者r&C:\raw\string& ? 数字:123.45 ? ? ?布尔值:true , false 序列:[&foo&, &bar&, 123.45] , 1..100? 哈希表:{&name&:&green mouse&, &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 & y, 等等 逻辑操作:!registered && (firstVisit || fromEurope) 内建函数:name?upper_case 方法调用:repeat(&What&, 3) 处理不存在的值 ? 默认值: name!&unknown& 或者(user.name)!&unknown& 或者 name! 或者 (user.name)!? 检测不存在的值:name?? 或者(user.name)?? 参考:运算符的优先级3.3.3 直接确定值通常我们喜欢是使用直接确定的值而不是计算的结果。3.3.3.1 字符串在文本中确定字符串值的方法是看引号和单引号,比如&some text& 或 'some text' ,这两种形式是相等的。如果文本本身包含用于字符引用的引号(双引号”或单引 号’)或反斜杠时,应该在它们的前面再加一个反斜杠,这就是转义。转义允许你直接在文 本中输入任何字符,也包括反斜杠。例如:${&It's \&quoted\& and this is a backslash: \\&} ${'It\'s &quoted& and this is a backslash: \\'} 输出为:It's &quoted& and this is a backslash: \ It's &quoted& and this is a backslash: \注意: 这里当然可以直接在模板中输入文本而不需要${…}。 但是我们在这里用它只是为了示例 来说明表达式的使用。 下面的表格是 FreeMarker 支持的所有转义字符。在字符串使用反斜杠的其他所有情况 都是错误的,运行这样的模板都会失败。 转义序列 含义\ 引号(u0022) \’ 单引号(又称为撇号) (u0027) \\ 反斜杠(u005C) \n 换行符(u000A) \r 回车(u000D) \t 水平制表符(又称为标签) (u0009) \b 退格(u0008) \f 换页(u000C) \l 小于号:& \g 大于号:& \a 和号:& \xCode 字符的 16 进制 Unicode 码(UCS 码) 在\x 之后的 Code 是 1-4 位的 16 进制码。下面这个示例中都是在字符串中放置版权 符号&\xA9 & , &\x0A9 & , &\x00A9 & :如果紧跟 16 进制码后一位的字符也能解释成 16 进制码时,就必须把 4 位补全,否则 FreeMarker 的解析就会出现问题。 注意字符序列${ #{ ) ( 有特殊的含义, 它们被用做插入表达式的数值 (典型的应用是: &Hello ${user}!& ) 。这将在后续章节中解释。如果想要打印${ ,就要使用下面所说 的原生字符串。 一种特殊的字符串就是原生字符串。在原生字符串中,反斜杠和${ 没有特殊的含义, 它们被视为普通的字符。 为了表明字符串是原生字符串, 在开始的引号或单引号之前放置字 母 r,例如:${r&${foo}&} ${r&C:\foo\bar&}将会打印:${foo} C:\foo\bar 3.3.3.2 数字输入不带引号的数字就可以直接指定一个数字, 必须使用点作为小数的分隔符而不能是 其他的分组分隔符。可以使用-或+ 来表明符号(+ 是多余的) 。科学记数法暂不支持使用 (1E3 就是错误的) ,而且也不能在小数点之前不写 0(.5 也是错误的) 。 下面的数字都是合法的:0.08, -5.013 , 8, 008 , 11, +11 。 数值文字 08 , +8 , 8.00 和 8 是完全相等的,它们都是数字 8。因此${08} , ${+8} , ${8.00} 和${8} 打印的都是相同的。3.3.3.3 布尔值直接写 true 或 false 就表征一个布尔值了,不需使用引号。3.3.3.4 序列指定一个文字的序列, 使用逗号来分隔其中的每个子变量, 然后把整个列表放到方括号 中。例如:&#list [&winter&, &spring&, &summer&, &autumn&] as x& ${x} &/#list&将会打印出:winter spring summer autumn列 表 中 的 项目 是 表达 式 ,那 么 也 可以 这 样做 : [2 + 2, [1, 2, 3, 4],&whatnot&] ,其中第一个子变量是数字 4,第二个子变量是一个序列,第三个子变量是字符串”whatnot”。 也可以用 start..end 定义存储数字范围的序列, 这里的 start 和 end 是处理数 字值表达式,比如 2..5 和[2, 3, 4, 5] 是相同的,但是使用前者会更有效率(内存 占用少而且速度快) 。可以看出前者也没有使用方括号,这样也可以用来定义递减的数字范 围,比如 5..2 。 (此外,还可以省略 end ,只需 5.. 即可,但这样序列默认包含 5,6,7,8 等递增量直到无穷大)3.3.3.5 哈希表在模板中指定一个哈希表,就可以遍历用逗号分隔开的“键/值”对,把列表放到花括 号内。键和值成对出现并以冒号分隔。看这个例子:{&name&:&green mouse&,&price&:150} 。注意到名字和值都是表达式,但是用来检索的名字就必须是字符串类 型的。3.3.4 检索变量 3.3.4.1 顶层变量为了访问顶层的变量,可以简单地使用变量名。例如,用表达式 user 就可以在根上 获取以“user”为名存储的变量值。然后就可以打印出存储在里面的内容。 ${user} 如果没有顶层变量,那么 FreeMarker 在处理表达式时就会发生错误,进而终止模板的 执行(除非程序员事先配置了 FreeMarker) 。 在这个表达式中变量名可以包含字母(也可以是非拉丁文) ,数字(也可以是非拉丁数 字) ,下划线(_),美元符号($),at 符号(@)和哈希表(#),此外要注意变量名命名时是不能以 数字开头的。3.3.4.2 从哈希表中检索数据如果有一个表达式的结果是哈希表,那么我们可以使用点和子变量的名字得到它的值, 假设我们有如下的数据模型:(root) | +- book | | | +- title = &Breeding green mouses& | | | +- author | | | +- name = &Julia Smith& | | | +- info = &Biologist, , Canada& | +- test = &title&现在, 就可以通过 book.title 来读取 title 表达式, book 将返回一个哈希表 (就 像 上 一 章中 解 释的 那样 ) 按 这 种逻 辑 进一 步 来说 ,我 们 可以 使 用表 达 式 。 book.author.name 来读取到 auther 的 name。 如果我们想指定同一个表达式的子变量,那么还有 另外一种语法格式:book[&title&] 。在方括号中可以给出任意长度字符串的表达式。在上面这个数据模型 示例中你还可以这么来获取 title:book[test] ,下面这些示例它们含义都是相等的: book.author.name , book[&author&].name , book.author.[&name&] , book[&author&][&name&] 。 当使用点式语法时,顶层变量名的命名也有相同的限制(命名时只能使用字母,数字, 下划线,$,@等) ,而使用方括号语法形式时命名有没有这样的限制,它可以是任意的表达 式。 (为了 FreeMarker 支持 XML,如果变量名是*(星号)或者**,那么就应该使用方括号 语法格式。 ) 对于顶层变量来说, 如果尝试访问一个不存在的变量也会引起错误导致模板解析执行的 中断(除非程序员事先配置过 FreeMarker) 。3.3.4.3 从序列中检索数据这和从哈希表中检索是相同的, 但是你只能使用方括号语法形式来进行, 而且方括号内 的表达式最终必须是一个数字而不是字符串。 在第一章的数据模型示例中, 为了获取第一个 动物的名字(记住第一项数字索引是 0 而不是 1)可以这么来写:animals[0].name 。3.3.4.4 特殊变量特殊变量是由 FreeMarker 引擎本身定义的,为了使用它们,可以按照如下语法形式来 进行:.variable_name 。 通常情况下是不需使用特殊变量, 而对专业用户来说可能用到。 所有特殊变量的说明可 以参见参考手册。3.3.5 字符串操作 3.3.5.1 插值(或连接)如果要在字符串中插入表达式的值,可以在字符串的文字中使用 ${…} ( #{…} ) 。${...}的作用和在文本区的是相同的。假设用户是”Big Joe”,看下面的代码:${&Hello ${user}!&} ${&${user}${user}${user}${user}&}将会打印如下内容:Hello Big Joe! Big JoeBig JoeBig JoeBig Joe另外,也可以使用+号来达到类似的效果,这是比较老的方法,也叫做字符串连接。示 例如下:${&Hello & + user + &!&} ${user + user + user + user}这样打印的效果和多次使用${...}是一样的。 警告: 使用者在使用插值时经常犯的一个错误是: 在不能使用插值的地方使用了它。 插值只能 在 文 本 区 段 ( &h1&Hello ${name}!&/h1& ) 和 字 符 串 文 字 ( &#include &/footer/${company}.html&& ) 中 使 用 。 一 个 典 型 的 错 误 使 用 是 &#if${isBig}&Wow!&/#if& , 这 是 语 法 上 的 错 误 。 只 能 这 么 来 写 : &#if isBig&Wow!&/#if& ,&#if &${isBig}&&Wow!&/#if& 来写也是错误的。因为 if 指令的参数需要的是布尔值,而这里是字符串,那么就会引起运行时的错误。3.3.5.2 获取一个字符在给定索引值时可以获取字符串中的一个字符,这和 3.3.4.3 节中从序列检索数据是相 似的,比如 user[0] 。这个操作执行的结果是一个长度为 1 的字符串,FTL 并没有独立的 字符类型。和序列中的子变量一样,这个索引也必须是数字,范围是从 0 到字符串的长度, 否则模板的执行将会发生错误并终止。 由于序列的子变量语法和字符的 getter 语法冲突, 那么只能在变量不是序列时使用字符 的 getter 语法(因为 FTL 支持多类型值,所以它是可能的) ,这种情况下使用序列方式就比 较多。 (为了变通,可以使用内建函数 string ,比如 user?string[0] 。不必担心你 不理解这个含义,内建函数将会在后续章节中讨论。 ) 看一个例子(假设 user 是”Big Joe”)${user[0]} ${user[4]}将会打印出(注意第一个字符的索引是 0) :B J注意: 可以按 照切 分序列 的方 式来 获取一 定范 围内 的字符 ,比 如 ${user[1..4]} 和${user[4..]} 。然而现在这种使用方法已经被废弃了,作为它的替代,可以使用内建 函数 substring ,内建函数将会在后续章节中讨论。3.3.6 序列操作 3.3.6.1 连接序列的连接可以使用+ 号来进行,例如:&#list [&Joe&, &Fred&] + [&Julia&, &Kate&] as user& - ${user} &/#list&将会打印出:-Joe Fred Julia Kate 要注意不要在很多重复连接时使用序列连接操作, 比如在循环中往序列上追加项目, 而 这样的使用是可以的:&#list users + admins as person& 。尽管序列连接的 很快, 而且速度是和被连接序列的大小相独立的, 但是最终的结果序列的读取却比原先的两 个序列慢那么一点。通过这种方式进行的许多重复连接最终产生的序列读取的速度会慢。3.3.6.2 序列切分

我要回帖

更多关于 起点中文网 的文章

 

随机推荐