freemarker中Bean的包装

时光毁灭记忆、已成空白 提交于 2019-12-11 02:57:05

reemarker.ext.beans.BeansWrapper 是一个对象包装器**, 最初加到FreeMarker中是为了将任意的POJO(Plan Old Java Objects,普通的Java对象) 包装成 TemplateModel 接口类型。** 这样它就可以以正常的方式来进行处理,事实上 DefaultObjectWrapper 本身是 BeansWrapper 的扩展类。
这里描述的所有东西对 DefaultObjectWrapper 都是适用的,
除了 DefaultObjectWrapper 会用到 freemarker.template.SimpleXxx 类包装的String,Number, Date,array,
Collection(如List), Map,Boolean 和 Iterator对象,会用 freemarker.ext.dom.NodeModel 来包装W3C的DOM结点(更多关于包装的W3C DOM 可以参考这里…), 所以上述这些描述的规则不适用。

模板方法模型功能(TemplateMethodModel functionality)
一个对象的所有方法作为 TemplateMethodModelEx 对象的表述, 它们在对象模型的方法名中使用哈希表的键来访问。
当使用 model.method(arg1, arg2, …) 来调用方法时,形参被作为模板模型传递给方法。 **方法首先不会包装它们,**后面我们会说到解包的详细内容。
这些不被包装的参数之后被实际方法来调用。以防止方法被重载, 许多特定的方法将会被选择使用相同的规则,也就是Java编译器从一些重载的方法中选择一个方法。 以防止没有方法签名匹配传递的参数,或者没有方法可以被无歧义地选择, 将会抛出 TemplateModelException 异常。

返回值类型为 void 的方法返回 TemplateModel.NOTHING,那么它们就可以使用 ${obj.method(args)} 形式的语法被安全地调用。

java.util.Map 实例的模型仍然实现了 TemplateMethodModelEx 接口,作为调用它们 get() 方法的一种方式。正如前面所讨论的那样, 你可以使用哈希表功能来访问"get"方法,但是它有一些缺点: 因为第一个属性和方法名会被键名来检查,所以执行过慢; 属性,方法名相冲突的键将会被隐藏;最终这种方法中你只可使用 String 类型的键。对比一下,调用 model(key) 方法,将直接翻译为 model.get(key):因为没有属性和方法名的查找, 速度会很快;不容易被隐藏;最终对非字符串的键也能正常处理, 因为参数没有被包装,只是被普通的方法调用。实际上, Map 中的 model(key) 和 model.get(key) 是相等的,只是写起来很短罢了。

java.util.ResourceBundle 类的模型也实现了 TemplateMethodModelEx 接口, 作为一种访问资源和信息格式化的方便形式。对资源包的单参数调用, 将会取回名称和未包装参数的 toString() 方法返回值一致的资源。 对资源包的多参数调用的情况和单参数一样,但是它会将参数作为格式化的模式传递给 java.text.MessageFormat,在第二个和后面的作为格式化的参数中使用未包装的值。 MessageFormat 对象将会使用它们原本的本地化资源包来初始化。

解包规则
如果目标对象是 boolean Map List Set 类型将会返回对应的模型对象

如果 目标对象 是 java.util.Collection 或 java.lang.Iterable 类型 除外,模型实现了 TemplateCollectionModel 或 TemplateSequenceModel 接口, 那么集合或序列模型(各自地)一个特殊的Set或List表示对象将会返回。

如果 T 是Java数组类型,模型实现了 TemplateSequenceModel 接口, 那么一个新的指定类型的数组将会创建, 它其中的元素使用数组的组件类型作为 T, 递归展开到数组中。
如果 T 是 char 或 java.lang.Character 类型,模型实现了 TemplateScalarModel 接口, 它的字符串表示中包含精确的一个字符,那么一个 java.lang.Character 类型的值将会返回。
如果 T 定义的是 java.util.Date 类型,模型实现了 TemplateDateModel 接口, 而且它的日期值是 T 的实例, 那么这个日期值将会返回。

字符串插入指南:不要忘了转义!
如果插值在 文本 区 (也就是说,不在 字符串表达式 中),如果 escape 指令 起作用了,那么将被插入的字符串会被自动转义。

freemarker 定义使用宏
macro可以有多个参数,参数的次序是无关的,在macro指令中只能使用定义的参数,并且必须对所有参数赋值,可以在定义参数时指定缺省值:
自定义指令嵌套内容 <#nested> ;<#nested>就相当于占位符

freemarker 中变量的使用 数据模型的变量【root中的变量】直接从模型中给模板传值的变量就是数据模型的变量,它把变量的值放在一个map中,在模板中直接可以用
【模板中的变量】:是使用<#assign定义的变量,如果模板中定义的变量和模型中的变量名称一致,不是覆盖,而是隐藏
局部变量【在指令中的变量】:使用local可以声明局部变量
循环变量【在循环中的变量】:在list循环中定义的变量,循环中的变量只在循环中有效,也是一种临时的变量定义方式

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!