On this page
2.3.24 (在 Apache 孵化)
Page Contents
发布日期:2016-03-28
这是一个稳定的最终版本. 在该项目成为完全被接受(分级)的 Apache 项目之前,Apache Software Foundation 要求使用“ incubating”后缀。请参阅下面的免责声明。
Legal changes
FreeMarker 的所有者现在是 Apache Software Foundation。与早期版本一样,该许可证仍为 Apache 许可证版本 2.0,但所有者有所不同。正式的完整产品名称已更改为 Apache FreeMarker。
FTL 方面的更改
此版本最重要的新功能是自动转义和输出格式机制,它不赞成使用escape directive进行转义。这些是与此新机制相关的更改(有关指南,请参见前面的链接):
新的
ftlHeaders 选项ouput_format和auto_esc可以覆盖模板的output_format和auto_escaping设置,例如<#ftl output_format='HTML'auto_esc=false>。全新内置:no_esc。用于防止自动转义,例如
${descriptionInHtml?no_esc}。这不适用于<#escape ...>,仅适用于新的自动转义机制。新的 FTL 类型,“标记输出”。这有点类似于字符串,但是这种类型的值不会被新的转义机制自动转义,因为已知它们已经保存了标记。 (例如,
?esc和?no_esc返回此类型的值,因此可以保护其结果免受双重转义问题的影响.)全新内置:esc。禁用自动转义时,用于以当前输出格式进行转义。
新内置的:
markup_string。这将返回标记输出值的标记作为字符串。新的内置函数:
is_markup_output,如果值的类型为“标记输出”,则返回true。新指令:
outputformat,用于更改模板某个部分(例如<#outputformat "XML">...</#outputformat>)的输出格式新指令:
noautoesc和autoesc,用于为模板的某个部分(如<#noautoesc>...</#noautoesc>)打开和关闭自动转义。新的内置变量
.output_format在调用位置返回当前输出格式。新的内置变量
.auto_esc返回一个布尔值,该布尔值指示调用时自动转义是否处于活动状态。当当前
output_format是某种标记(例如 HTML)时,像<#assign captured>...</#assign>这样的块分配将不以字符串类型而是以“标记输出”类型存储捕获的输出。因此${captured}不会发生不必要的转义。+运算符(串联)也适用于新的“标记输出”类型。像someMarkup + somePlainText一样,会产生标记,其中somePlainText在附加到标记之前会自动转义。内置
has_content现在支持“标记输出”值,将 0 长度标记视为空。
现在,您可以定义自定义数字和日期/时间/日期时间格式化程序。这些是由程序员定义的(因此可以实现任何种类的奇异格式设置规则),它们在配置 FreeMarker 时可以以
"@"开头的字符串(如<#setting number_format='@foo'>或${n?string.@foo_params},<#setting number_format='@foo params'>或${n?string.@foo},${n?string.@foo_params})进行引用。为了向后兼容,如果您有任何自定义格式或incompatible_improvements 设置至少为 2.3.24,则首字母@仅具有此特殊含义。现在,在使用 Java
DecimalFormat模式的任何地方(例如?string('0.##')或<#setting number_format="0.##">),都可以使用特定于 FreeMarker 的DecimalFormat 模式语法的扩展来指定舍入模式或使用的符号之类的选项。添加了新的特殊变量:
.incompatible_improvements,以字符串形式返回当前 FreeMarker 配置的incompatible_improvements setting。现在可以将
?date,?time和?datetime称为 0 参数方法,例如?date()等,它返回TemplateDateFormat.parse返回的确切对象,而不是仅使用?date返回的棘手的多类型对象。由于自定义TemplateDateFormat实现可能返回自定义TemplateDateModel实现,因此在某些应用程序中,保持准确的类可能很重要。现在,包含
${exp}的字符串 Literals 中允许<@和</@,它们将照原样作为 Literals 的一部分。之前是语法错误。修正了错误:将
incompatible_improvements设置为 2.3.24(看看这里如何...)时,对于由BeansWrapper及其子类(最著名的DefaultObjectWrapper)包装的 Java 方法,m?is_sequence不再返回true,因为它们仅实现[index]运算符,而不实现?size,这导致<#list ...>失败等等。
Java 方面的更改
注意! FreeMarker 现在至少需要 Java 1.5(又名 Java 5)。 2.3.24 仅需要 Java 1.4. (原因:没有这个,新的公共 API 不能使用泛型,这会对大多数用户造成负面影响,而仍然使用 1.4 的旧安装无论如何都不太可能更新 FreeMarker.)
注意! FreeMarker 的 JSP 支持(如果已使用)现在至少需要 JSP 2.0. 此前,它仅需要 JSP 1.1. (原因:构建所需的 JSP 1.x 的
jsp-api依赖关系不能合法存在于 Maven 中央存储库中,也不能由 freemarker.org 提供.)添加了新的配置设置:
template_configurations。这允许根据模板名称模式覆盖来自共享Configuration对象的单个模板的设置。 在这里查看更多...与新的自动转义机制相关:
由于 FTL 现在有一个新类型“标记输出”,因此还有一个相应的新模型接口
TemplateMarkupOutputModel。这也意味着您可以通过返回TemplateMarkupOutputModel而不是String来防止自动转义来自数据模型的值。就像模板作者可以只写${messages.foo}一样,它会自动转义还是不转义,这取决于消息是否已知为标记。添加了新的配置设置:
recognize_standard_file_extensions。当true时,其源名称以".ftlh"结尾的模板将获得HTMLoutput_format,而其名称以".ftlx"结尾的模板将获得XMLoutput_format,在两种情况下均启用自动转义。如果incompatible_improvements 设置设置为 2.3.24(或更高),则此设置默认为true。否则,默认值为false,但强烈建议启用它。添加了新的配置设置:
output_format。这指定用于控制自动转义的output format对象(例如HTMLOutputFormat.INSTANCE,XMLOutputFormat.INSTANCE等)。使用template_configurations设置(看这里如何...),不同模板的输出格式可以不同。添加了新的配置设置:
registered_custom_output_formats。这样,您可以添加新的OutputFormat-s,模板可以通过名称来引用它们(例如<#ftl output_format="foo">)。添加了新的配置设置:
auto_escaping_policy。这决定了何时应根据当前输出格式启用自动转义。
与自定义编号和日期/时间/日期时间格式设置功能有关的更改:
添加了用于实现自定义格式化程序的新类:
freemarker.core.TemplateNumberFormat,TemplateNumberFormatFactory,TemplateDateFormat,TemplateDateFormatFactory,以及这些类可能引发的异常。这些允许实现 Java 中可行的任何类型的格式化规则(即,它们不限于任何java.text格式化程序)。此外,这些格式化程序将获得TemplateModel而不是裸露的java.lang.Number或java.util.Date,这使您可以使用可以打包到TemplateModel-s 中的额外的特定于应用程序的元信息,例如物理单位,首选精度等。添加了
custom_number_formats和custom_date_formats设置(Configurable.setCustomNumberFormats(Map<String, TemplateNumberFormatFactory>)和Configurable.setCustomDateFormats(Map<String, TemplateDateFormatFactory>)),您可以使用它们设置自己的格式。这些格式可以从任何地方引用,您可以在任何地方使用字符串来定义格式,格式字符串如"@foo"或"@foo params",其中"foo"是前面显示的方法的Map<String, ...>参数中的键,而参数(如果有)是由您提供的TemplateXxxFormatFactory实现解释。像,您可以发出cfg.setNumberFormat("@foo params")或<#setting number_format='@foo params'>或${n?string.@foo_params},类似于发出cfg.setNumberFormat("0.##"),等等。为了向后兼容,如果您有任何自定义格式或incompatible_improvements 设置至少为 2.3.24,则初始@仅具有特殊含义。请注意,可以针对每个模板(通过新的template_configurations设置)或针对每个Environment设置custom_number_formats和custom_date_formats设置,因此@foo在不同的模板中可能有所不同。添加了新的
Environment方法,返回了TemplateNumberFormat和TemplateDateFormat个对象。请参阅 API 中的getTemplateNumberFormat(...)和getTemplateDateFormat(...)变体。添加了
freemarker.core.AliasTemplateNumberFormatFactory和AliasTemplateDateFormatFactory,可用于创建自定义格式,这些自定义格式是其他格式的别名。例如,您可以定义自定义格式"price"作为配置中格式字符串"0.00"的别名,而不是一遍又一遍地写${n?string["0.00"]},然后使用${n?string.@price}。因此,您可以在中心位置控制价格的样子。此外,别名可以根据当前语言环境选择不同的目标格式字符串。这对于约会特别有用,因为约会在不同国家/地区可能会有很大差异。现在可以在数字和日期/时间/日期时间格式结果中包含 HTML 或其他标记,例如
1.23*10<sup>6</sup>,因为 FreeMarker 知道它已经是 HTML 了,所以不会意外转义。这是通过返回TemplateMarkupOutputModel而不是String来完成的;请参阅前面的新自动转义机制。请注意,目前还没有开箱即用的格式使用此格式,但是您可以编写这种自定义格式。内部格式对象缓存体系结构已经过重新设计,因此它也可以处理自定义格式。这种重做还解决了在高并发负载下的某些瓶颈,以及一些(否则不太可能)内存泄漏的可能性。
在
number_format配置设置中,当它持有 JavaDecimalFormat模式(如"0.##")时,现在可以使用 FreeMarker 特定的模式语法的扩展来指定舍入模式或所用符号等选项。新的
FreemarkerServletinit-params(有关详细信息,请参见FreemarkerSerlvet API 文档):OverrideResponseContentType:指定何时应覆盖HttpServletResponse中已设置的contentType(即非null)。之前,我们一直在设置它,这仍然是默认行为。但是,既然此 init-param 存在,则可以更改该行为,以便在转发到FreemarkerServlet之前指定的contentType很重要。OverrideResponseLocale:指定是否应覆盖HttpServletResponse中已设置的locale(即非null)。之前,我们总是进行设置,但是现在可以更改此行为,以便仅在尚未设置的情况下进行设置。ResponseCharacterEncoding:不赞成使用旧的(古怪的)逻辑来指定输出字符集,即将其放在 MIME 类型之后的ContentTypeinit-param 中,否则返回模板文件字符集。可能的值为legacy(向后兼容的默认值),fromTemplate(不带怪异的legacy,并且知道outputEncoding设置),doNotSet(保留调用方在ServletRespone中已经设置的内容)和force,后跟一个字符集名称(强制使用特定的输出字符集)。
添加了
freemarker.cache.ByteArrayTemplateLoader,类似于StringTemplateLoader,但是将模板存储为byte[]-s 而不是String-s。将 JavaCC(在构建过程中用于生成 FTL 解析器)从 3.2 升级到 6.1.2.
添加了
Configurable.getSettingNames(boolean camelCase),它返回一组有效的设置名称。这对于自动完成等很有用。修复和改进了用于从
java.util.Properties或其他仅字符串源(在模板中未使用)配置 FreeMarker 的“对象构建器”微型语言。 不要与模板语言语法混淆,后者与我们在此处编写的“对象构建器”语法无关。改进之处包括:修正了错误:对于嵌套的生成器表达式,意外应用了顶级结果类限制。
在解析诸如
com.example.Foo()的表达式时,如果存在构建器类(com.example.FooBuilder),则不再需要非构建器类(com.example.Foo)。毕竟,FooBuilder.build()从它想要的任何类实例化。可以像
TimeZone("UTC")一样创建TimeZone对象,尽管没有这样的构造函数。添加了对使用
[ item1, item2, ... itemN ]语法创建列表的支持。添加了对使用
{ key1: value1, key2: value2, ... keyN: valueN }语法创建 Map 的支持。现在,根据数字的大小,没有小数点的数字将被解析为
Integer,Long或BigInteger。早先所有数字都解析为BigDecimal-s,但是在添加列表和 Map 之前这没有什么意义,因为无论如何该数字都已转换为构造函数或 setter 参数类型。数字 Literals 可以具有 Java 类型后缀(
f,d,l),加上bd表示BigDecimal和bi表示BigInteger。可以引用公共静态字段,例如
com.example.MyClass.MY_CONSTANT或Configuration.AUTO_DETECT_TAG_SYNTAX。
减少了模板执行的堆栈使用率,如果您有非常深层嵌套的模板,这可能很重要。
添加了
MultiTemplateLoader.setSticky(boolean)和MultiTemplateLoader.isSticky(),您可以使用它们禁用默认行为,即一旦在子TemplateLoader中找到模板,则下次将在该模板中首次搜索(通常,当模板更新延迟到期时)。将sticky属性设置为false时,子TemplateLoader-s 将始终按添加到MultiTemplateLoader的 Sequences 进行搜索。添加了
StringTemplateLoader.removeTemplate(String)方法。错误已修复,仅将
incompatible_improvements设置为 2.3.24(看看这里如何...):内插表达式位于字符串 Literals 表达式内(通常不是${...}-s),例如<#assign s="Hello ${name}!">,始终使用incompatibleImprovements0 0(实际上是 2.3.0) 。这意味着字符串 Literals 内的表达式缺少?html,?iso_...,?is_enumerable,?c等修复/改进。错误修复\ [439]:__
emulateCaseSensitiveFileSystem设置为true(用于开发)的FileTemplateLoader未正确同步,从而导致随机NullPointerException-s 或其他异常行为。错误修正:Java
Iterator被认为是空的时,定义不正确。根据您使用的ObjectWrapper,可以应用以下修复程序之一:DefaultObjectWrapper(修复程序始终处于活动状态):Iterator上的操作仅检查其是否为空而不从中读取一个元素(例如?has_content),不会导致以后的迭代(或进一步的空度检查)失败。早些时候,在某些情况下,第二个操作失败,说迭代器“只能列出一次”。BeansWrapper(当它不由DefaultObjectWrapper扩展时),如果它的incompatibleImprovements属性设置为 2.3.24(或更高):Iterator-s 在使用?has_content时总是被认为是非空的(例如,运算符检查空度而不读取)任何元素)。现在,如果Iterator没有剩余元素,则完全计为空。 (请注意,此错误从未影响过基本功能,例如<#list ...>.)
错误修正:
ParseException-s 的(罕见)原因异常未设置错误修正:现有
Configuration的incomaptible_improvements设置发生更改时,有时不会重新创建模板缓存,因此旧模板可以保留下来。已修复错误,并且将
incompatible_improvements设置为 2.3.24(看看这里如何...):#import指令用于将库变量复制到全局变量(如果它在主命名空间中执行),但是当导入的模板较早导入时并没有发生另一个名称空间。修复了 XML 处理功能(
freemarker.ext.dom):错误修正:XPath 查询仅包含在 XML 元素名称中有效的字符,并且还包含
::(在不使用名称空间的文档中的名称中有效),例如e['following-sibling::foo'],被解释为原义元素名称(命中 0)比作为 XPath 表达式。请注意,例如e['following-sibling::*']并没有这样的问题,因为根据 XML 规范,它不是有效的 XML 元素名称。此修补程序实际上可以破坏已处理了使用::作为元素或属性名称一部分的,未处理名称空间的 XML 的应用程序,但是与遇到已解决的问题不同,这种应用程序的可能性很小。 (不幸的是,在技术上无法使用incompatible_improvements.)修正了错误:通过
<#ftl ns_prefixes={'D':'...', ... }>声明为默认名称的 XML 名称空间的元素@@qname不再以D:开头,而是不再以名称空间前缀开头。修正了错误:在
@@markup键返回的标记中,当多个命名空间没有与 via<#ftl ns_prefixes=...>相关联的前缀时,所有这些命名空间都被分配了相同的自动生成的xmlns前缀(通常为“ a”)。现在,他们将获得“ a”,“ b”,“ c”等前缀。
现在,JSP TLD 加载引用了
jar-s(和其他zip-s)的位置,由于错误消息中的 zip 格式错误,该位置无法加载。向具有
namingConvention参数的Configuration.getSupportedBuiltInNames和Configuration.getSupportedBuiltInDirectiveNames添加了重载。从 2.3.23 开始,这对工具很有用,因为我们既支持驼峰命名约定(如s?upperCase)又支持传统的驼峰命名约定(如s?upper_case)。此外,旧的 0 参数重载现在将使用Configuration.getNamingConvention()来返回相关名称,如果不是AUTO_DETECT_NAMING_CONVENTION。内部重做以简化 AST(
TemplateElement结构)。相关的技术上公开的 API 在很长一段时间内都被标记为内部。对于那些仍在使用该 API 的人来说,可见的变化是TemplateElement-s 现在几乎不再具有MixedContent父级,相反,当您查看源代码时,父级直接是子元素确实所属的任何元素(例如#list例如,较早的时候,您通常必须先通过MixedContent,其父代是#list)。请注意,当您向下移动(即移向子元素)时,这些MixedContent父级不可见,并且会被静默跳过,因此树遍历 API 不一致。现在是一致的。再次由于上述更改,返回类型
freemarker.core.DebugBreak.accept()和freemarker.core.TextBlock.accept()从void更改为TemplateElement[]。这再次极不可能影响任何人,并且无论如何都意味着它们是内部 API,但是由于历史原因,由于这两种accept方法具有比程序包可见性更大的功能,因此我们提到了这一更改。freemarker.core.StringLiteral-s 的非公开 AST API 已更改。从原则上讲,它不是公共 API,因此并不重要,但是有些人可能会使用这些来进行内省模板。之前它内部有一个“嵌入式模板”参数,现在它具有 0(用于纯静态字符串 Literals),一个或多个“值部分” -s,即String-s 和Interpolation-s。内部代码清理:主要用于一致的源代码格式,也可以进行许多解析器构造/设置清理
源代码进行了更改,以符合 Apache 源代码发布策略,例如添加版权 Headers 和摆脱提交到源代码中的测试
jar-s。 Eclipse 项目文件也被删除,相反README描述了如何设置项目。构建脚本和分发工件更改以符合 Apache 发布策略,最值得注意的是,它会生成单独的源代码和二进制版本。
与 2.3.24 版本候选 1 相比的更改
添加了
MultiTemplateLoader.setSticky(boolean)和MultiTemplateLoader.isSticky(),您可以使用它们禁用默认行为,即一旦在子TemplateLoader中找到模板,则下次将在该模板中首次搜索(通常,当模板更新延迟到期时)。将sticky属性设置为false时,子TemplateLoader-s 将始终按添加到MultiTemplateLoader的 Sequences 进行搜索。添加了
StringTemplateLoader.removeTemplate(String)方法。源代码更改符合 Apache 发行 Policy 和建议:
不再将二进制测试
jar-s 提交到源代码中(而是即时生成)- Eclipse 项目文件已删除,相反,
README描述了如何设置项目。
- Eclipse 项目文件已删除,相反,