2.3.24 (在 Apache 孵化)

Page Contents

发布日期:2016-03-28

这是一个稳定的最终版本. 在该项目成为完全被接受(分级)的 Apache 项目之前,Apache Software Foundation 要求使用“ incubating”后缀。请参阅下面的免责声明。

FreeMarker 的所有者现在是 Apache Software Foundation。与早期版本一样,该许可证仍为 Apache 许可证版本 2.0,但所有者有所不同。正式的完整产品名称已更改为 Apache FreeMarker。

FTL 方面的更改

  • 此版本最重要的新功能是自动转义和输出格式机制,它不赞成使用escape directive进行转义。这些是与此新机制相关的更改(有关指南,请参见前面的链接):

  • 新的ftlHeaders 选项ouput_formatauto_esc可以覆盖模板的output_formatauto_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>)的输出格式

    • 新指令:noautoescautoesc,用于为模板的某个部分(如<#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"结尾的模板将获得HTML output_format,而其名称以".ftlx"结尾的模板将获得XML output_format,在两种情况下均启用自动转义。如果incompatible_improvements 设置设置为 2.3.24(或更高),则此设置默认为true。否则,默认值为false,但强烈建议启用它。

    • 添加了新的配置设置:output_format。这指定用于控制自动转义的output format对象(例如HTMLOutputFormat.INSTANCEXMLOutputFormat.INSTANCE等)。使用template_configurations设置(看这里如何...),不同模板的输出格式可以不同。

    • 添加了新的配置设置:registered_custom_output_formats。这样,您可以添加新的OutputFormat -s,模板可以通过名称来引用它们(例如<#ftl output_format="foo">)。

    • 添加了新的配置设置:auto_escaping_policy。这决定了何时应根据当前输出格式启用自动转义。

  • 与自定义编号和日期/时间/日期时间格式设置功能有关的更改:

  • 添加了用于实现自定义格式化程序的新类:freemarker.core.TemplateNumberFormatTemplateNumberFormatFactoryTemplateDateFormatTemplateDateFormatFactory,以及这些类可能引发的异常。这些允许实现 Java 中可行的任何类型的格式化规则(即,它们不限于任何java.text格式化程序)。此外,这些格式化程序将获得TemplateModel而不是裸露的java.lang.Numberjava.util.Date,这使您可以使用可以打包到TemplateModel -s 中的额外的特定于应用程序的元信息,例如物理单位,首选精度等。

    • 添加了custom_number_formatscustom_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_formatscustom_date_formats设置,因此@foo在不同的模板中可能有所不同。

    • 添加了新的Environment方法,返回了TemplateNumberFormatTemplateDateFormat个对象。请参阅 API 中的getTemplateNumberFormat(...)getTemplateDateFormat(...)变体。

    • 添加了freemarker.core.AliasTemplateNumberFormatFactoryAliasTemplateDateFormatFactory,可用于创建自定义格式,这些自定义格式是其他格式的别名。例如,您可以定义自定义格式"price"作为配置中格式字符串"0.00"的别名,而不是一遍又一遍地写${n?string["0.00"]},然后使用${n?string.@price}。因此,您可以在中心位置控制价格的样子。此外,别名可以根据当前语言环境选择不同的目标格式字符串。这对于约会特别有用,因为约会在不同国家/地区可能会有很大差异。

    • 现在可以在数字和日期/时间/日期时间格式结果中包含 HTML 或其他标记,例如1.23*10<sup>6</sup>,因为 FreeMarker 知道它已经是 HTML 了,所以不会意外转义。这是通过返回TemplateMarkupOutputModel而不是String来完成的;请参阅前面的新自动转义机制。请注意,目前还没有开箱即用的格式使用此格式,但是您可以编写这种自定义格式。

    • 内部格式对象缓存体系结构已经过重新设计,因此它也可以处理自定义格式。这种重做还解决了在高并发负载下的某些瓶颈,以及一些(否则不太可能)内存泄漏的可能性。

  • number_format配置设置中,当它持有 Java DecimalFormat模式(如"0.##")时,现在可以使用 FreeMarker 特定的模式语法的扩展来指定舍入模式或所用符号等选项。

  • 新的FreemarkerServlet init-params(有关详细信息,请参见FreemarkerSerlvet API 文档):

  • OverrideResponseContentType:指定何时应覆盖HttpServletResponse中已设置的contentType(即非null)。之前,我们一直在设置它,这仍然是默认行为。但是,既然此 init-param 存在,则可以更改该行为,以便在转发到FreemarkerServlet之前指定的contentType很重要。

    • OverrideResponseLocale:指定是否应覆盖HttpServletResponse中已设置的locale(即非null)。之前,我们总是进行设置,但是现在可以更改此行为,以便仅在尚未设置的情况下进行设置。

    • ResponseCharacterEncoding:不赞成使用旧的(古怪的)逻辑来指定输出字符集,即将其放在 MIME 类型之后的ContentType init-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 的支持。

    • 现在,根据数字的大小,没有小数点的数字将被解析为IntegerLongBigInteger。早先所有数字都解析为BigDecimal -s,但是在添加列表和 Map 之前这没有什么意义,因为无论如何该数字都已转换为构造函数或 setter 参数类型。

    • 数字 Literals 可以具有 Java 类型后缀(fdl),加上bd表示BigDecimalbi表示BigInteger

    • 可以引用公共静态字段,例如com.example.MyClass.MY_CONSTANTConfiguration.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 的(罕见)原因异常未设置

  • 错误修正:现有Configurationincomaptible_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.getSupportedBuiltInNamesConfiguration.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描述了如何设置项目。