我的用例是为用户提供借助模板引擎创建报告的可能性。因此,我提取了数据模型的相关部分并将Freemarker集成为模板引擎。
到目前为止,它运行良好,但是现在我的数据模型在某些位置包含继承-但是Freemarker似乎不支持instanceof操作?该如何处理?模型中还有其他支持继承的模板引擎吗?
虚构的例子:
我有2类"汽车"和"自行车",它们扩展了"车辆"。该模型包含一个"车辆编队"类,其中包含一系列车辆。用户希望(借助模板)遍历该列表,并在汽车的情况下编写属性" countSeats",在自行车的情况下编写属性" frame size"。 Freemarker如何做到这一点?可以在任何模板引擎中完成吗?
提前谢谢了!
//编辑:不幸的是,不可能将具有超类的列表拆分为带有" concrete"对象的多个列表,因为列表中车辆的顺序(在上述示例中)是必不可少的。
freemarker是否支持在列表中的对象上调用任意java方法? 如果是这样,则可以使用Object.getClass();。 丑陋但可行,希望有更好的方法。
我从未使用过FreeMarker,但是您认为可以使用访问者模式取代对instanceof的需求吗?
@Kasper:它确实支持调用任意Java方法。
Uglier解决方案
something
#if>
do something else
#if> `
没有为此内置任何内容,但也不必如此。 您可以编写自己的TemplateMethodModelEx,或将简单的Java帮助程序对象放入数据模型以执行几乎所有操作。 或者,您可以将相关类放入数据模型中,例如root.put("Car", Car.class)等,然后使用Class的Java API,如下所示:
非常感谢你。 但我担心我没有收到您的建议。 我得到了第二个关于将Car.class放入模型的信息-可以执行instanceof检查,但是我还需要强制转换为该实例,使用此选项将无法实现? 第一个关于编写我自己的TemplateMethodModelEx的信息-您更详细地表示什么? 检查了源,但我不知道您的建议的主意。
铸造是什么意思? FTL是动态类型的,您不需要进行强制转换。 (从TemplateMethodModelEx开始,从JavaDoc应该很清楚如何实现它,然后,如果将其放入数据模型或Configuration级共享变量中,则可以在诸如。)
使用TemplateMethodModelEx的解决方案。
类:
public class InstanceOfMethod implements TemplateMethodModelEx {
@Override
public Object exec(List list) throws TemplateModelException
{
if (list.size() != 2) {
throw new TemplateModelException("Wrong arguments for method 'instanceOf'. Method has two required parameters: object and class");
} else {
Object object = ((WrapperTemplateModel) list.get(0)).getWrappedObject();
Object p2 = ((WrapperTemplateModel) list.get(1)).getWrappedObject();
if (!(p2 instanceof Class)) {
throw new TemplateModelException("Wrong type of the second parameter. It should be Class. Found:" + p2.getClass());
} else {
Class c = (Class) p2;
return c.isAssignableFrom(object.getClass());
}
}
}
}
将该类的实例和所有必需的类放入模板的输入参数:
parameters.put("instanceOf", new InstanceOfMethod());
parameters.put("Car", Car.class);
...
或者,您可以将方法添加到共享变量:http://freemarker.org/docs/pgui_config_sharedvariables.html
因此,您可以按以下方式使用FTL中的方法:
...
#if>