在 Freemarker 模板中迭代 HashMap 显示地图的方法

Iterating over HashMap in Freemarker template displays map's methods

在 Apache OfBiz 应用程序中,我在控制器中有这样的代码:

   public static String runRequest(HttpServletRequest request, HttpServletResponse response) {
        Map<String, Long> typesToCount = getTypesToCount();
        request.setAttribute("types", typesToCount);
        return HttpFinals.RETURN_SUCCESS;
   }

在 freemarker 模板中它是 processed/iterated 像这样:

<table
<#list requestAttributes.types as key, value>
    <tr>
        <td>${key}</td>
        <td>${value}</td>
    </tr>
</#list>
</table>

在呈现的 html 页面上,我得到了实际地图的字符串键和地图的方法名称(放置、删除、添加等)。

至于值,它们根本没有呈现,并出现以下错误:

FreeMarker template error: For "${...}" content: Expected a string or something automatically convertible to string (number, date or boolean), or "template output" , but this has evaluated to a method+sequence (wrapper: f.e.b.SimpleMethodModel)

我正在使用 freemarker 2.3.28

如果 FreeMarker 配置为使用纯 BeansWrapper(而不是 DefaultObjectWrapper)作为其 object_wrapper 设置,并且 BeansWrapper.simpleMapWrapper 属性 保留其默认值 false。不用说,这是一个非常有问题的配置。希望它不是 OfBiz 的默认值。尽管对于旧框架来说,这可能会发生,但在许多年前,这是一种解决 FreeMarker 某些限制的方法,因为这样您就可以只使用 Map 的 Java API。后来,?api 内置函数的引入使这个 hack 变得不必要了。

Map.entrySet() 方法 returns 此映射中包含的映射的集合 (Set<Map.Entry<K, V>>)。所以我们可以使用 Map.Entry<K, V> 的 getKey() 和 getValue() 方法迭代键值对。此方法最常见,如果您在循环中同时需要映射键和值,则应使用此方法。

尝试使用此代码循环访问 FTL 中的值

<table>
  <#list requestAttributes.entrySet() as requestAttribute>
  <tr>
    <td>${requestAttribute.getKey()}</td>
    <td>${requestAttribute.getValue()}</td>
  </tr>
  </#list>
</table>

基本上,只有在将地图包装在 SimpleMapModel 中后,我才设法遍历地图,如下所示:

   public static String runRequest(HttpServletRequest request, HttpServletResponse response) {
       Map<String, Long> typesToCount = getTypesToCount();
       request.setAttribute("types",  new SimpleMapModel(typesToCount, new DefaultObjectWrapper())));
       return HttpFinals.RETURN_SUCCESS;
    }

和 int ftl 模板:

   <#list requestAttributes.types?keys as key>
   <tr>
       <td>${key}</td>
       <td>${requestAttributes.types[key]}</td>
   </tr>
   </#list>