我有一个HashMap作为Map<Long, List<Map<String, Object>>> typeAndKno,在FreeMarker页面中,我得到了这张地图的内容如下:
<#list typeAndKno?keys as typeId>
${typeAndKno.get(typeId).get(0).get('TYPE_NAME')}
<#list typeAndKno.get(typeId) as kno>
${kno.get('KNOWLEDGE_ID')}
</#list>
</#list>此代码在Struts2中运行良好,但在迁移到Spring之后,代码将失败。最后,我将代码更改为:
<#list typeAndKno?keys as typeId>
${typeAndKno[typeId]?first['TYPE_NAME']}
<#list typeAndKno[typeId?string] as kno>
${kno['KNOWLEDGE_ID']}
</#list>
</#list>这两段代码有什么区别?是否有办法使第一段代码在Spring中工作?
发布于 2013-08-28 15:05:16
更新:
从2.3.22开始,有一个更简单、无干扰的解决方案:配置FreeMarker使?api工作,然后您可以使用Java of Map,其中键不是String-s。有关详细信息,请参阅此常见问题条目或这个答案。
现在,Strut的FreeMarker设置非常不受欢迎。当然,在当时,当他们这么做的时候,这也许是最合理的解决办法,但现在已经不是了,尤其是在2.3.22之后。
旧答案(过时):
从模板中看到Java的方式取决于所使用的ObjectWrapper,这是一个FreeMarker配置设置。根据您的示例,Struts使用带有默认设置的BeansWrapper,而Spring可能使用DefaultObjectWrapper。所以这就导致了差异。我不建议使用这两种方法,因为:
BeansWrapper及其默认设置,Map键与方法名混合,方法名具有优先级。当然,您可以安全地使用myMap.get(key)来解决这个问题,但是与myMap.foo相比,myMap.get('foo')非常糟糕,因为与myMap.foo相比,myMap.foo只有在没有方法称为foo的情况下才能工作。此外,?keys将返回一个混合的真实键和方法名称与它..。真是一团糟。DefaultObjectWrapper,您可以安全地编写myMap.foo,但是您将无法获得具有非字符串键的实体,因为myMap[key]只支持字符串,并且不再有myMag.get(key)。所以我通常在FreeMarker中使用的是一个bw = new BeansWrapper(); bw.setSimpleMapWrapper(true)。这样,Map-s的方法是不可见的,就像使用DefaultObjectWrapper一样,所以您可以安全地使用myMap.foo和myMap[key]。但是,如果很少需要使用非字符串键,则可以使用myMap(nonStringKey) (是的,使用()而不是[])。最后一种方法不适用于DefaultObjectWrapper。(希望FreeMarker 2.4能解决这个混乱的非字符串键废话,但它不会在短期内推出.)
因此,下一个问题是如何使用Spring设置对象包装。我不在家。据我所见,您有一个FreeMarkerConfigurer bean,它有一个freemarkerSettings属性,它是一个最终传递给FreeMarker的Properties-based配置API的Properties对象。因此,您应该可以添加一个object_wrapper属性,该属性引用要使用的ObjectWrapper的类名(也可以像Struts那样只使用beans来使用默认的BeansWrapper实例)。问题是,基于属性的API是相当有限的,因此您不能同时在那里创建和配置(调用setSimpleMapWrapper) BeansWrapper。当然,您可以在spring配置文件中这样做,但我看不到将其注入FreeMarkerConfigurer的方法,除非您将整个freemarker.template.Configuration对象作为bean创建,并将其注入带有configuration属性的FreeMarkerConfigurer中。因此,最简单的解决方法可能是扩展BeansWrapper以覆盖simpleMapWrapper的默认值,然后通过object_wrapper引用该扩展类的类。(万一以后有人读到这一点,FreeMarker 2.3.21很可能会扩展属性配置API,以便您只需将object_wrapper设置为BeansWrapper() { simpleMapWrapper = true }。)
https://stackoverflow.com/questions/18449159
复制相似问题