簡體   English   中英

將構造函數導出到FreeMarker數據模型中

[英]exporting constructors into the FreeMarker data model

有什么方法可以將特定的類構造函數導出到FreeMarker數據模型中?

ObjectConstructor提供了訪問任何可訪問的構造函數的能力:

Java的:

myDataModel.put("objectConstructor", new ObjectConstructor()); 

模板:

<#assign aList = objectConstructor("java.util.ArrayList", 100)>

但是我不想那樣做。 如果我有一個帶有兩個構造函數Foo(int x)Foo(String name, int x)的類Foo ,我想以某種方式將一個對象導出為Foo到數據模型中,以便可以在模板中執行此操作:

<#assign myfoo1 = Foo(1) >
<#assign myfoo2 = Foo("Buffalo Bill", 2) >

我可以使用TemplateMethodModelEx手動執行此操作,但它需要我實現exec(List arguments)並弄清楚如何拉出參數並將其推入Foo類構造函數中。

我想要的是一個ClassConstructor對象,該對象接受相關Class<T>參數,並實現TemplateMethodModelEx並自動進行強制轉換,就像FreeMarker自動處理Java對象方法調用一樣,我可以在Java中完成此操作:

myDataModel.put("Foo", new ClassConstructor(Foo.class));

有沒有辦法做到這一點?

從FTL調用Java方法和構造函數是BeansWrapper的業務,它也是DefaultObjectWrapper和您在那里找到的大多數自定義ObjectWrapper的超類。 因此, ObjectWrapper.newInstance(Class clazz, List/*<TemplateModel>*/ arguments)可以為您完成棘手的部分。 其他的則是一些瑣碎的工作(我在這里花了點時間來獲取ObjectWrapper這是可選的):

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

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM