Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将构造函数导出到FreeMarker数据模型中_Java_Freemarker - Fatal编程技术网

Java 将构造函数导出到FreeMarker数据模型中

Java 将构造函数导出到FreeMarker数据模型中,java,freemarker,Java,Freemarker,有没有办法将特定的类构造函数导出到FreeMarker数据模型中 提供访问任何可访问构造函数的权限: 爪哇: 模板: <#assign aList = objectConstructor("java.util.ArrayList", 100)> 我可以使用手动执行此操作,但它需要我实现exec(列出参数),并找出如何提取参数并将它们推送到我的Foo类构造函数中 我想要的是一个ClassConstructor对象,它接受所讨论的类的Class参数,实现TemplateMethodMo

有没有办法将特定的类构造函数导出到FreeMarker数据模型中

提供访问任何可访问构造函数的权限:

爪哇:

模板:

<#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;
    }

}