有4种类型的标量:

  • 布尔值
  • 数字
  • 字符串
  • 日期类型(子类型: 日期(没有时间部分),时间或者日期-时间)

每一种标量类型都是 TemplateTypeModel 接口的实现,这里的 Type 就是类型的名称。这些接口只定义了一个方法: type getAsType();。 它返回变量的Java类型(booleanNumberStringDate 各自代表的值)。

Note:

由于历史遗留的原因,字符串标量的接口是 TemplateScalarModel,而不是 TemplateStringModel。 (因为早期的 FreeMarker 字符串就是标量。)

这些接口的一个细小的实现和 SimpleType 类名在 freemarker.template 包中是可用的。 但是却没有 SimpleBooleanModel 类型;为了代表布尔值, 可以使用 TemplateBooleanModel.TRUETemplateBooleanModel.FALSE 来单独使用。

Note:

由于历史遗留的原因,字符串标量的实现类是 SimpleScalar,而不是 SimpleString

在FTL中标量是一成不变的。当在模板中设置变量的值时, 使用其他的实例来替换 TemplateTypeModel 实例时, 是不用改变原来实例中存储的值的。

"日期" 类型的难点

对于日期类型来说,有一些难题,因为Java API通常不区别 java.util.Date 只存储日期部分(April 4, 2003), 时间部分(10:19:18 PM),或两者都存(April 4, 2003 10:19:18 PM)。 为了用本文正确显示值(或者进行其它确定的操作),FreeMarker必须知道 java.util.Date 的哪个部分存储了有意义上的信息, 哪部分没有被使用(通常是标记为0的)。不幸的是, 通常该信息只是当值从数据库中取得时可用, 因为大多数数据库有独立的日期,时间和日期-时间(又叫做时间戳)类型, java.sql 有3个对应的 java.util.Date 子类和它们相匹配。

TemplateDateModel 接口有两个方法:分别是 java.util.Date getAsDate()int getDateType()。 该接口典型的实现是存储一个 java.util.Date 对象, 加上一个整数来辨别子类型。这个整数的值也必须是 TemplateDateModel 接口中的常量之一:DATETIMEDATETIMEUNKNOWN

关于 UNKNOWN: java.langjava.util 下的类通常被自动转换成 TemplateModel 的实现类,就是所谓的 对象包装器ObjectWrapper(请参考之前的对象包装介绍)。 如果对象包装器要包装 java.util.Date 类, 它不是 java.sql 日期类的实例,那就不能决定子类型是什么, 所以使用 UNKNOWN。之后,如果模板需要使用这个变量, 而且操作也需要子类型,那就会停止执行并抛出错误。为了避免这种情况的发生, 对于那些可能有问题的变量,模板开发人员必须明确地指定子类型,使用内建函数 datetimedatetime (比如 lastUpdated?datetime)。请注意, 如果和格式化参数一起使用内建函数 string, 比如foo?string("MM/dd/yyyy"),那么 FreeMarker 就不必知道子类型了。