FreeMarker的复杂类型集合(FreeMarker Complex Collection)

2019-10-18 13:36发布

我有一个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 MVC的后,代码失败。 我终于改变了代码如下:

<#list typeAndKno?keys as typeId>
    ${typeAndKno[typeId]?first['TYPE_NAME']}
    <#list typeAndKno[typeId?string] as kno>
         ${kno['KNOWLEDGE_ID']}
    </#list>
</#list>

什么是这两段代码之间的区别? 有没有一种方法,以使第一段代码工作的Spring MVC中?

Answer 1:

更新:

作为2.3.22有这个更简单的和非破坏性的解决方案:FreeMarker的配置,这样?api作品,然后你可以使用的Java API的Map ,其中键是不是String -s。 见这个FAQ条目或这个答案的更多细节。

和支柱的FreeMarker的设置是什么,我们强烈劝阻现在。 当然,回去以后,当他们这样做,这是可能是最合理的解决办法,但它已不再一会儿,并自2.3.22特别是没有。

老答案(过时):

你看到的模板Java对象的方式取决于ObjectWrapper使用,这是一个FreeMarker的配置设置。 根据你的榜样,Struts使用一个BeansWrapper其默认设置,而Spring可能使用DefaultObjectWrapper 。 这样导致的差异。 我不建议您使用,这是因为:

  • 随着BeansWrapper使用其默认设置Map键和方法名混合,具有优先级的方法名。 当然,你可以放心地使用myMap.get(key)要解决这个问题,但myMap.get('foo')相比,仅仅是可怕myMap.foo ,这将仅就你有没有所谓的工作方法foo 。 也?keys返回真实密钥和方法名的混合物与它...它是一个烂摊子。

  • 随着DefaultObjectWrapper您可以安全地写myMap.foo ,但你将无法得到与非字符串键的实体,因为myMap[key]仅支持字符串,你不必myMag.get(key)了。

所以我也通常与FreeMarker的使用是bw = new BeansWrapper(); bw.setSimpleMapWrapper(true) bw = new BeansWrapper(); bw.setSimpleMapWrapper(true) 。 有了这个,方法Map -s是不可见的,就像DefaultObjectWrapper ,所以你可以使用myMap.foomyMap[key]安全。 但是,如果你很少需要得到的东西与非字符串键,你可以使用myMap(nonStringKey)是的,有()代替[] 这最后一个不工作DefaultObjectWrapper 。 (希望FreeMarker的2.4将解决这个烂摊子非字符串键废话,但它不喜欢它会掉很快...)

所以,接下来的问题就是如何设置与Spring的对象包装。 我不在家那里。 据我看到的,你有一个FreeMarkerConfigurer豆具有freemarkerSettings属性,它是一个Properties多数民众赞成最终传递到的FreeMarker的对象Properties为基础的配置API。 所以你应该能够添加object_wrapper是指的类名属性ObjectWrapper使用(或者它可能只是beans使用默认BeansWrapper比如像Struts的可能一样)。 问题在于,基于属性的API是相当有限的,所以你不能同时创建和配置(调用setSimpleMapWrapper )一BeansWrapper那里。 你可以做到这一点当然Spring配置文件中,但我不明白的方式来注入到FreeMarkerConfigurer ,除非你创建整个 freemarker.template.Configuration对象作为一个bean,并注入该进FreeMarkerConfigurerconfiguration它的属性。 因此,也许最简单的解决方法是扩大BeansWrapper覆盖默认simpleMapWrapper ,然后通过参照类,延伸类的object_wrapper 。 (万一有人读这以后,它可能在FreeMarker 2.3.21,这样你可以设置将扩展属性配置API object_wrapperBeansWrapper() { simpleMapWrapper = true } 。)



文章来源: FreeMarker Complex Collection