FreeMarker综合收藏 [英] FreeMarker Complex Collection

查看:104
本文介绍了FreeMarker综合收藏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在FreeMarker页面中,我有一个Map<Long, List<Map<String, Object>>> typeAndKno的HashMap,我得到的地图内容如下:

I've got a HashMap as Map<Long, List<Map<String, Object>>> typeAndKno, in the FreeMarker page, I get the content of this map like this:

<#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之后,该代码将失败.我终于将代码更改为此:

This code works fine in Struts2, but after moved to Spring MVC, the code fails. I finally changed the code to this:

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

这两段代码有什么区别?有没有一种方法可以使第一部分代码在Spring MVC中工作?

What's the difference between these two pieces of code? Is there a way to make the first piece of code work in Spring MVC?

推荐答案

更新:

从2.3.22版开始,有一个更简单且无中断的解决方案:配置FreeMarker以便?api起作用,然后您可以使用Map的Java API,其中键不是String -s.请参见此FAQ条目

As of 2.3.22 there's a much easier and non-disruptive solution for this: configure FreeMarker so that ?api works, and then you can use the Java API of Map where the keys aren't String-s. See this FAQ entry or this answer for more details.

现在强烈反对Strut的FreeMarker设置.当然,那时候,当他们这样做的时候,那也许是最合理的解决方法,但这已经有一段时间了,尤其是从2.3.22开始.

And Strut's FreeMarker setup is something that's strongly discouraged now. Of course, back then, when they did that, that was maybe the most reasonable workaround, but it isn't anymore for a while, and especially not since 2.3.22.

旧答案(过时):

从模板查看Java对象的方式取决于所使用的ObjectWrapper,这是FreeMarker配置设置.根据您的示例,Struts使用BeansWrapper及其默认设置,而Spring可能使用DefaultObjectWrapper.这样就造成了差异.我不建议使用任何一种,因为:

The way you see Java objects from templates depends on the ObjectWrapper used, which is a FreeMarker configuration setting. Based on your example, Struts uses a BeansWrapper with its default settings, while Spring possibly uses the DefaultObjectWrapper. So that causes the differences. I wouldn't recommend using either, because:

  • 具有BeansWrapper的默认设置Map键与方法名称混合,其中方法名称优先.当然,您可以安全地使用myMap.get(key)来解决此问题,但是与myMap.foo相比,myMap.get('foo')简直太可怕了,仅当您没有称为foo的方法时,它才有效.同样,?keys会返回包含实键和方法名的混合信息……这是一团糟.

  • With BeansWrapper with its default settings Map keys mix with the method names, with method names having priority. Surely you can safely use myMap.get(key) to get around that, but myMap.get('foo') is just horrible compared to myMap.foo, which will only work as far you have no method called foo. Also ?keys will return a mixture of real keys and method names with it... it's a mess.

使用DefaultObjectWrapper您可以安全地编写myMap.foo,但是您将无法获得带有非字符串键的实体,因为myMap[key]仅支持字符串,而您没有了.

With DefaultObjectWrapper you can safely write myMap.foo, but you won't be able to get entities with non-string keys, because myMap[key] only support strings, and you don't have myMag.get(key) anymore.

所以我通常在FreeMarker上使用的是bw = new BeansWrapper(); bw.setSimpleMapWrapper(true).这样,Map -s的方法就不可见,就像DefaultObjectWrapper一样,因此您可以安全地使用myMap.foomyMap[key].但是,如果很少需要使用非字符串键来获取内容,则可以使用myMap(nonStringKey)(是的,使用()而不是[]).这最后一个不适用于DefaultObjectWrapper. (希望FreeMarker 2.4可以解决非字符串键的问题,但这并不是很快就会消失的.)

So what I have usually used with FreeMarker was a bw = new BeansWrapper(); bw.setSimpleMapWrapper(true). With this, the methods of Map-s are not visible, just like with DefaultObjectWrapper, so you can use myMap.foo and myMap[key] safely. But if rarely you need to get something with a non-string key, you can use myMap(nonStringKey) (yes, with () instead of []). This last doesn't work with DefaultObjectWrapper. (Hopefully FreeMarker 2.4 will solve this mess with non-string keys nonsense, but it's not like it will be out anytime soon...)

因此,下一个问题是如何使用Spring设置对象包装.我不在家.据我所知,您有一个FreeMarkerConfigurer bean,它具有一个freemarkerSettings属性,该属性是一个Properties对象,最终将其传递给FreeMarker基于Properties的配置API.因此,您应该能够添加一个object_wrapper属性,该属性引用要使用的ObjectWrapper的类名(或者可能只是beans来使用默认的BeansWrapper实例,就像Struts所做的那样).问题是,基于属性的API相当有限,因此您不能同时在其中创建和配置(调用setSimpleMapWrapper)一个BeansWrapper.您当然可以在spring配置文件中执行此操作,但是除非您将 whole freemarker.template.Configuration对象创建为bean,否则我看不到将其注入FreeMarkerConfigurer的方法.使用它的configuration属性将其注入FreeMarkerConfigurer中.因此,最简单的解决方法可能是扩展BeansWrapper以覆盖默认的simpleMapWrapper,然后通过object_wrapper引用该扩展类的类. (以防万一以后有人阅读,FreeMarker 2.3.21可能会扩展属性配置API,以便您可以将object_wrapper设置为BeansWrapper() { simpleMapWrapper = true }.)

So the next question is how to set the object wrapper with Spring. I'm not at home there. As far as I see, you have a FreeMarkerConfigurer bean which has a freemarkerSettings property, which is a Properties object that's eventually is passed to FreeMarker's Properties-based configuration API. So there you should be able add an object_wrapper property that refers to the class name of the ObjectWrapper to use (or it could just be beans to use the default BeansWrapper instance like maybe Struts does). Problem is, the property-based API is rather limited, and so you can't both create and configure (call setSimpleMapWrapper) a BeansWrapper there. You could do that in the spring configuration file of course, but I don't see a way to inject that into the FreeMarkerConfigurer, unless you create the whole freemarker.template.Configuration object as a bean, and inject that into the FreeMarkerConfigurer with the configuration property of it. So maybe the easiest workaround is extending BeansWrapper to override the default of simpleMapWrapper, and then referring to the class of that extending class via object_wrapper. (Just in case somebody reads this later, it's probable that FreeMarker 2.3.21 will extended the properties configuration API so that you can just set object_wrapper to BeansWrapper() { simpleMapWrapper = true }.)

这篇关于FreeMarker综合收藏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆