<#list> 中 Iterable 的 FreeMarker 错误

FreeMarker error with Iterable in <#list>

在 FreeMarker 模板中,我将变量传递给 <#list>:

<#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)
...

怎么回事?

(如果其他人 运行 参与其中,我将通过问答来解决这个问题 - 我在这里没有找到它)

这里的问题是变量是 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

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

Tip: The problematic value is a java.lang.Iterable. Using DefaultObjectWrapper(..., iterableSupport=true) as the object_wrapper setting of the FreeMarker configuration should solve this.

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

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

Spring

的示例

在控制器中

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

在模板中

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