Java FreeMarker:将 ${variable} 替换为集合而不是对象的实例

Java FreeMarker: Replacing a ${variable} with a collection instead of an instance of an object

我是 FreeMarker 的新手,我正在尝试构建一个 HTML 文件用于报告目的。

我能够掌握基础知识 - 例如用对象替换某个 ${user} 变量。

问题:
我正在尝试使用以下模板创建 HTML table。 ${summaryTable.rowData} 将被一系列 <tr> 取代。 1 tr 是对象的 1 个实例。我无法使用下面的代码实现这一点,而是我只能从循环中获取最后一个实例。

我在这里错过了什么?

详情请见下方

模板:

....
            <thead>
               <tr id="header">
                  <td><b>Module</b></font></td>
                  <td><b>Passed</b></font></td>
                  <td<b>Failed</b></font></td>
               </tr>
            </thead>
            <tbody>
               ${summaryTable.rowData}
            </tbody>
...

代码:

        // Start Building HTML
        Map<String, Object> root = new HashMap<String, Object>();
        // Header variables
        root.put("environment", envDir);
        root.put("reportDateTimeStamp", dateDir);

        // Summary Table
        for (String module : getAllModules(rawResult)) {
            SummaryTable summaryTable = new SummaryTable();
            int modPassed = getModulePassFailCount(rawResult, module).get(GlobalUtil.reportLabelPassed);
            int modFailed = getModulePassFailCount(rawResult, module).get(GlobalUtil.reportLabelFailed);

            summaryTable.setRowData(
                    getSummaryData(module, Integer.toString(modPassed), Integer.toString(modFailed)));
            root.put("summaryTable", summaryTable);
        }

        DetailsTable detailsTable = new DetailsTable();
        detailsTable.setRowData(getDetailsData("MOD1", "TC01", "Description 01", "Passed", "00:00:00"));

        root.put("detailsTable", detailsTable);

        OutputStream outputStream = new FileOutputStream(htmlResultFile);
        Writer out = new OutputStreamWriter(outputStream, charSet);
        temp.process(root, out);
        out.close();

setRowData() 接受单个字符串 - 在这种情况下,<tr> 的 1 个实例包含每个 module 迭代的 N 个 <td>

型号:

public static class SummaryTable {
    private String rowData;

    public String getRowData() {
        return rowData;
    }

    public void setRowData(String rowData) {
        this.rowData = rowData;
    }
}

输出:
实际:

预期:

============================================= ===========================
更新 1:
我已经根据下面 rrobby 的回答更新了我的模板、代码和模型。

模板:

....
            <thead>
               <tr id="header">
                  <td><b>Module</b></font></td>
                  <td><b>Passed</b></font></td>
                  <td<b>Failed</b></font></td>
               </tr>
            </thead>
            <tbody>
               <#list summaryTable as summaryTable.rowData>
                <tr>
                ${summaryTable.rowData}
                </tr>
               </#list>
            </tbody>
...

代码:

        // Start Building HTML
        Map<String, Object> root = new HashMap<String, Object>();
        // Header variables
        root.put("environment", envDir);
        root.put("reportDateTimeStamp", dateDir);

        // Summary Table
        ArrayList<SummaryTable> summaryTable = new ArrayList<SummaryTable>();
        for (String module : getAllModules(rawResult)) {
            int modPassed = getModulePassFailCount(rawResult, module).get(GlobalUtil.reportLabelPassed);
            int modFailed = getModulePassFailCount(rawResult, module).get(GlobalUtil.reportLabelFailed);

            summaryTable.add(new SummaryTable(
                    getSummaryData(module, Integer.toString(modPassed), Integer.toString(modFailed))));
        }
        root.put("summaryTable", summaryTable);

        DetailsTable detailsTable = new DetailsTable();
        detailsTable.setRowData(getDetailsData("MOD1", "TC01", "Description 01", "Passed", "00:00:00"));

        root.put("detailsTable", detailsTable);

        OutputStream outputStream = new FileOutputStream(htmlResultFile);
        Writer out = new OutputStreamWriter(outputStream, charSet);
        temp.process(root, out);
        out.close();

setRowData() 接受单个字符串 - 在这种情况下,<tr> 的 1 个实例包含每个 module 迭代的 N 个 <td>

型号:

public static class SummaryTable {
    private String rowData;

    public String getRowData() {
        return rowData;
    }

    public void setRowData(String rowData) {
        this.rowData = rowData;
    }

    public SummaryTable(String rowData) {
        this.rowData = rowData;
    }
}

我遇到异常:

freemarker.core.ParseException: Syntax error in template "ReportTemplate.html" in line 100, column 63:
Encountered ".", but was expecting one of:
    ","
    ">"

第 100 行指向 <#list summaryTable as summaryTable.rowData>

希望对您有所帮助。

对于列表和表格,您通常应该将项目放入集合中并使用 <#list> 标记对其进行迭代,解释为 here

例如:

<table>
  <thead>...</thead>
  <tbody>
    <#list summaryTable as row>
      <tr><td>${row.foo}</td><td>${row.bar}</td>...</tr>
    </#list>
  </tbody>
</table>

设法让它发挥作用。 Rrobby 的提示有所帮助,但他的回答并不完整。

模板(语法):

    <tbody>
       <#list yourObject as anyVariable>
       <tr>
          ${anyVariable.aPropertyOfYourObject}
       </tr>
       </#list>
    </tbody>

模板(实际):

    <tbody>
       <#list summaryTable as summaryData>
       <tr>
          ${summaryData.rowData}
       </tr>
       </#list>
    </tbody>

代码:

// Summary Table
ArrayList<SummaryTable> summaryTable = new ArrayList<SummaryTable>();
for (String module : getAllModules(rawResult)) {
    int modPassed = getModulePassFailCount(rawResult, module).get(GlobalUtil.reportLabelPassed);
    int modFailed = getModulePassFailCount(rawResult, module).get(GlobalUtil.reportLabelFailed);

    summaryTable.add(new SummaryTable(
            getSummaryData(module, Integer.toString(modPassed), Integer.toString(modFailed))));
    root.put("summaryTable", summaryTable);
}

型号:

public static class SummaryTable {
    private String rowData;

    public String getRowData() {
        return rowData;
    }

    public void setRowData(String rowData) {
        this.rowData = rowData;
    }

    public SummaryTable(String rowData) {
        this.rowData = rowData;
    }
}

我错误地使用了 #list 指令,我需要将 root.put("summaryTable", summaryTable); 放在循环中。

更改后得到正确的输出。感谢帮助过的人!