Java 将构造函数导出到FreeMarker数据模型中
有没有办法将特定的类构造函数导出到FreeMarker数据模型中 提供访问任何可访问构造函数的权限: 爪哇: 模板:Java 将构造函数导出到FreeMarker数据模型中,java,freemarker,Java,Freemarker,有没有办法将特定的类构造函数导出到FreeMarker数据模型中 提供访问任何可访问构造函数的权限: 爪哇: 模板: <#assign aList = objectConstructor("java.util.ArrayList", 100)> 我可以使用手动执行此操作,但它需要我实现exec(列出参数),并找出如何提取参数并将它们推送到我的Foo类构造函数中 我想要的是一个ClassConstructor对象,它接受所讨论的类的Class参数,实现TemplateMethodMo
<#assign aList = objectConstructor("java.util.ArrayList", 100)>
我可以使用手动执行此操作,但它需要我实现exec(列出参数)
,并找出如何提取参数并将它们推送到我的Foo
类构造函数中
我想要的是一个ClassConstructor
对象,它接受所讨论的类的Class
参数,实现TemplateMethodModelEx
并自动执行强制转换,就像FreeMarker自动处理Java对象方法调用一样,我可以在Java中这样做:
myDataModel.put("Foo", new ClassConstructor(Foo.class));
有办法做到这一点吗?从FTL调用Java方法和构造函数是
BeansWrapper
的工作,它也是DefaultObjectWrapper
的超类,也是您在那里找到的大多数自定义ObjectWrapper
-s的超类。因此,ObjectWrapper.newInstance(类clazz,List/**/arguments)
可以为您完成棘手的部分。其他的是一些简单的管道(我在这里有点喜欢使用ObjectWrapper
——这是可选的):
package freemarker.adhoc;
导入java.util.List;
导入freemarker.core.Environment;
导入freemarker.ext.beans.BeansWrapper;
导入freemarker.template.Configuration;
导入freemarker.template.ObjectWrapper;
导入freemarker.template.TemplateMethodModelEx;
导入freemarker.template.TemplateModelException;
/**
*创建调用给定类的构造函数的FTL方法。支持重载和varargs。
*/
公共类构造函数TemplateModel实现TemplateMethodModelEx{
私有最终类构造函数类;
私有最终BeansWrapper对象包装器;
/**
*@param objectWrapper
*与{@link Configuration}或{@code null}中使用的{@link ObjectWrapper}相同
*查找每个构造函数调用的当前{@link ObjectWrapper}(较慢)。
*/
公共构造函数模板模型(类构造函数类、BeansWrapper对象包装器){
this.constructorClass=constructorClass;
this.objectWrapper=objectWrapper;
}
@凌驾
public Object exec(List/**/arguments)抛出TemplateModelException{
BeansWrapper objectWrapper=this.objectWrapper;
if(objectWrapper==null){
objectWrapper=getCurrentBeansWrapper();
}
返回objectWrapper.newInstance(构造函数类,参数);
}
私有BeansWrapper getCurrentBeansWrapper(){
Environment env=Environment.getCurrentEnvironment();
if(env==null){
抛出新的IllegalStateException(“无正在进行的模板处理”);
}
ObjectWrapper=env.getObjectWrapper();
if(!(BeansWrapper的objectWrapper实例)){
抛出新的IllegalStateException(“对象包装器必须是BeansWrapper.object包装器类:”
+objectWrapper.getClass().getName());
}
return(BeansWrapper)objectWrapper;
}
}
。。。这里有点困惑:为什么不创建一个DefaultObjectWrapper
的静态实例并使用它调用newInstance()
?我很困惑为什么要做这件事需要任何有状态的东西;给定所讨论的参数列表和类
,这难道不足以毫不含糊地调用构造函数吗?当您使用对象包装器
包装对象时(在本例中,对象就是构造函数),您将从模板中看到该对象的方式,您通过该对象看到对象的方式,以此类推,将取决于相同的初始ObjectWrapper
。因此,如果在配置
中有一个自定义的ObjectWrapper
,或者甚至只有一个使用不同于默认设置的DefaultObjectWrapper
,那么您当然希望在任何地方都使用它。
<#assign myfoo1 = Foo(1) >
<#assign myfoo2 = Foo("Buffalo Bill", 2) >
myDataModel.put("Foo", new ClassConstructor(Foo.class));
package freemarker.adhoc;
import java.util.List;
import freemarker.core.Environment;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
/**
* Creates an FTL method that calls the constructor of the given class. Supports overloading and varargs.
*/
public class ConstructorTemplateModel implements TemplateMethodModelEx {
private final Class constructorClass;
private final BeansWrapper objectWrapper;
/**
* @param objectWrapper
* The same {@link ObjectWrapper} used in the {@link Configuration}, or {@code null} if we should
* find the current {@link ObjectWrapper} for each constructor call (slower).
*/
public ConstructorTemplateModel(Class<?> constructorClass, BeansWrapper objectWrapper) {
this.constructorClass = constructorClass;
this.objectWrapper = objectWrapper;
}
@Override
public Object exec(List/*<TemplateModel>*/ arguments) throws TemplateModelException {
BeansWrapper objectWrapper = this.objectWrapper;
if (objectWrapper == null) {
objectWrapper = getCurrentBeansWrapper();
}
return objectWrapper.newInstance(constructorClass, arguments);
}
private BeansWrapper getCurrentBeansWrapper() {
Environment env = Environment.getCurrentEnvironment();
if (env == null) {
throw new IllegalStateException("No ongoing template processing");
}
ObjectWrapper objectWrapper = env.getObjectWrapper();
if (!(objectWrapper instanceof BeansWrapper)) {
throw new IllegalStateException("The object wrapper must be a BeansWrapper. Object wrapper class: "
+ objectWrapper.getClass().getName());
}
return (BeansWrapper) objectWrapper;
}
}