【问题标题】:FreeMarker error with Iterable in <#list><#list> 中的 Iterable 出现 FreeMarker 错误
【发布时间】:2018-03-04 16:59:58
【问题描述】:

在 FreeMarker 模板中,我将一个变量传递给 &lt;#list&gt;

<#list sectorTags as sector>
     <td colspan="${sector.designatedTags!?size}">${sector.name}</td>
<#else>
     <td>No technology sectors defined.</td>
</#list>

但是失败了:

06:25:03,733 SEVERE freemarker.core.NonSequenceOrCollectionException: Expected a sequence or collection, but this has evaluated to an extended_hash+string (com.tinkerpop.frames.structures.FramedVertexIterable wrapped into f.e.b.StringModel):
==> sectorTags  [in template "reports/templates/techReport-punchCard.ftl" at line 105, column 32]
----
FTL stack trace ("~" means nesting-related):
    - Failed at: #list-#else-container  [in template "reports/templates/techReport-punchCard.ftl" at line 105, column 25]
----
    at freemarker.core.IteratorBlock$IterationContext.executeNestedBlockInner(IteratorBlock.java:295)
...

发生了什么事?

(如果其他人遇到这个问题,我会通过问答来解决这个问题 - 我在这里没有找到)

【问题讨论】:

    标签: freemarker


    【解决方案1】:

    这里的问题是变量是Iterable。 FreeMarker 目前无法处理该问题(即将Iterable 转换为IteratorCollection)。

    Iterable 必须明确转换为 Iterator

    <#list sectorTags.iterator() as sector>
         <td colspan="${sector.designatedTags!.iterator()?size}">${sector.name}</td>
    <#else>
         <td>No technology sectors defined.</td>
    </#list>
    

    Iteratable 没有被自动隐藏的原因在 Jira 问题(我现在找不到)中进行了讨论。如果我没记错的话,那是因为Java中有一些类型是Iterable,但不希望自动将它们变成Iterators

    【讨论】:

    • 为了以后的读者,FreeMarker确实支持直接列出Iterable-s(无需转换)。这是一个配置问题;有关更多信息,请参阅我的答案。
    【解决方案2】:

    您需要开启Iterable 支持。为了向后兼容,默认情况下它是关闭的。您可能还应该升级 FreeMarker,因为至少在当前版本中,错误消息还包含以下内容:

    提示:有问题的值是 java.lang.Iterable。使用 DefaultObjectWrapper(..., iterableSupport=true) 作为 object_wrapper FreeMarker 配置的设置应该可以解决这个问题。

    其中,当您使用 Java API 配置 FreeMarker 时,看起来像这样:

    DefaultObjectWrapperBuilder owb = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_26);
    owb.setIterableSupport(true);
    cfg.setObjectWrapper(owb.build());
    

    【讨论】:

    【解决方案3】:

    Spring 示例

    在控制器中

    model.addAttribute("blogItems", blogItems);
    return "main";
    

    在模板中

    <#list blogItems.iterator() as blogItem>
       ${blogItem.name}
    </#list>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-18
      • 1970-01-01
      • 2012-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-26
      • 2011-06-24
      相关资源
      最近更新 更多