有4种类型的标量:
- 布尔值
- 数字
- 字符串
- 日期类型(子类型: 日期(没有时间部分),时间或者日期-时间)
每一种标量类型都是
TemplateTypeModel
接口的实现,这里的 Type
就是类型的名称。这些接口只定义了一个方法:
type
getAsType();
。
它返回变量的Java类型(boolean
,
Number
, String
和
Date
各自代表的值)。
由于历史遗留的原因,字符串标量的接口是
TemplateScalarModel
,而不是
TemplateStringModel
。
(因为早期的 FreeMarker 字符串就是标量。)
这些接口的一个细小的实现和
SimpleType
类名在 freemarker.template
包中是可用的。
但是却没有 SimpleBooleanModel
类型;为了代表布尔值,
可以使用 TemplateBooleanModel.TRUE
和
TemplateBooleanModel.FALSE
来单独使用。
由于历史遗留的原因,字符串标量的实现类是
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
接口中的常量之一:DATE
, TIME
,
DATETIME
和 UNKNOWN
。
关于 UNKNOWN
: java.lang
和 java.util
下的类通常被自动转换成
TemplateModel
的实现类,就是所谓的
对象包装器ObjectWrapper
(请参考之前的对象包装介绍)。
如果对象包装器要包装 java.util.Date
类,
它不是 java.sql
日期类的实例,那就不能决定子类型是什么,
所以使用 UNKNOWN
。之后,如果模板需要使用这个变量,
而且操作也需要子类型,那就会停止执行并抛出错误。为了避免这种情况的发生,
对于那些可能有问题的变量,模板开发人员必须明确地指定子类型,使用内建函数 date
,
time
或 datetime
(比如 lastUpdated?datetime
)。请注意,
如果和格式化参数一起使用内建函数 string
,
比如foo?string("MM/dd/yyyy"),那么 FreeMarker 就不必知道子类型了。