【问题标题】:Using Freemarker to display a table of arbitrary Java objects and their fields使用 Freemarker 显示任意 Java 对象及其字段的表
【发布时间】:2016-12-11 03:51:06
【问题描述】:

首先,我阅读了this question,但它并没有解决我的问题。

我正在尝试创建一个可以显示任意 Java 对象列表的表。当我说“任意”时,我的意思是对象的数量是任意的,对象的类型是任意的(尽管它们都将是同一类的实例)。我希望该表的行表示对象,而列表示每个对象的实例变量的值(基本上是电子表格样式)。然而,第一行将只是实例变量名称的列表。

我目前正在测试的对象已将所有变量设置为私有,但我提供了相关的 getter 和 setter。

这是我的 Java 代码中的一个 sn-p。我从 Oracle Coherence 缓存中提取对象,并将它们放入 ArrayList。然后我创建一个实例变量名称的字符串数组。:

        /**
     * Get objects in cache and add to ArrayList.
     */

    for(Iterator iter = currentCache.entrySet().iterator();iter.hasNext();){
        Map.Entry entry = (Map.Entry)iter.next();
        String key = (String) entry.getKey();
        Pof tempPof = (Pof)entry.getValue();
        tableList.add(tempPof);
        System.out.println("one loop");
    }

    request.setAttribute("beans",tableList);

    System.out.println("Size of tableList is: " + tableList.size());
    /**
     * Build an array containing the variable names of cached objects.
     */

    Field[] fields = Pof.class.getDeclaredFields();
    String[] variableNames = new String[fields.length];

    for(int j = 0; j < fields.length;j++){
        variableNames[j] = fields[j].getName();
        System.out.println(variableNames[j]);
    }

    request.setAttribute("colNames",variableNames);


    /**
     * numCols determines the number of columns displayed in the table.
     */

    int numCols = fields.length;
    String[] fieldStrings = new String[numCols];
    request.setAttribute("numCols",numCols);
    Pof thing = (Pof) tableList.get(0);

这是来自相关 .ftl 文件的 sn-p:

<table border = "1px">
        <thead>
            <tr>
                <th colspan="${numCols}">${selectedCache}</th>
            </tr>
            <tr>
                <#list colNames as colName>
                    <td>${colName}</td>
                </#list>
            </tr>
        </thead>
        <tbody>
            <#list beans as bean>
                <tr>
                    <#list colNames as colName>
                        <td>${bean[colName]}</td>
                    </#list>
                </tr>
            </#list>
        </tbody>

    </table>

这让我得到以下错误:


freemarker.core.InvalidReferenceException:以下已评估为 null 或缺失: ==> bean[colName] [在模板“front.ftl”中,第 46 行,第 35 列]

提示:导致此错误的是最后的 [] 步骤,而不是之前的步骤。

提示:如果已知失败的表达式合法地引用了有时为 null 或缺失的内容,请指定一个默认值,如 myOptionalVar!myDefault,或使用 when-presentwhen -失踪。 (这些仅涵盖表达式的最后一步;要涵盖整个表达式,请使用括号:(myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? FTL 堆栈跟踪(“~”表示嵌套相关): - 失败于:${bean[colName]} [在模板“front.ftl”中,第 46 行,第 33 列]

at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:451)
at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:374)
at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:96)
at freemarker.core.DollarVariable.accept(DollarVariable.java:59)
Truncated. see log file for complete stacktrace

问题似乎是我的 ftl 语法;也就是说,它不喜欢表达式 ${bean[colName]}。

问题:

1) 语法错了吗?

2) 这是 Freemarker 做不到的吗?

3) 我应该尝试其他方法吗?例如,我是否应该只创建一个数组,每个存储桶都包含一个实例变量值的数组(或另一个数据结构)?

【问题讨论】:

    标签: java freemarker


    【解决方案1】:

    它应该可以工作,前提是:

    • Pof 是公共类
    • 每个colName "foo" 都有一个公共Pof.getFoo() 方法
    • getFoo() 返回非null 值。如果它有时返回null,则必须指定要显示的内容,例如:${bean[colName]!'-'}

    【讨论】:

    • 生成了我的表格!但是有很多空字段。当我检查发送给 FreeMarker 的对象的值时,它们不为空。似乎没有遵循变量类型或值的模式。但我确实注意到返回 null 的变量以单个大写字母开头(例如“Big_Contracts”),而 FreeMarker 成功访问的实例变量以两个大写字母开头(例如“LG_Contracts”)。 FreeMarker 在用于从哈希中检索数据时是否会对这些字符串的大小写做些什么?
    • FreeMarker 不关心字段(好吧,它可以配置为读取公共字段,但现在已经不在主题范围内了)。它关心 JavaBeans 属性。因此,变量名称是根据 JavaBeans 规范指定的规则从 getter 方法名称推导出来的。对于getBigContacts,属性名称为bigContacts。奇怪的是,getLGContacts() 的属性名称是 LGContacts... 这些规则不是由 FreeMarker 定义的,而是由 JavaBeans 规范定义的。
    猜你喜欢
    • 2011-02-13
    • 2018-10-06
    • 2023-03-29
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 2011-05-24
    • 2018-06-29
    相关资源
    最近更新 更多