Freemarker:如何使用枚举作为键遍历 Map

Posted

技术标签:

【中文标题】Freemarker:如何使用枚举作为键遍历 Map【英文标题】:Freemarker: How to iterate through the Map using enums as keys 【发布时间】:2011-07-22 07:11:49 【问题描述】:

以下代码不起作用,因为 Freemarker 似乎将 [] 内的表达式的值转换为 String,然后将其用作键,这不是实际预期的。

准备模板模型:

Map<MyEnum, Object> myMap;
myMap.put(MyEnum.FOO, "Foo");
myMap.put(MyEnum.BAR, "Bar");
templateModel.put("myMap", myMap);

我的.ftl:

<#list myMap?keys as key>
    <#assign value = myMap[key]>
    <li>$key = $value</li>
</#list>

Freemarker documentation 中描述了如何访问 Enum 本身,但我没有找到任何关于如何使用 Enum 作为键从哈希中获取值的信息。

谢谢。

【问题讨论】:

【参考方案1】:

接受的答案不是自 2.3.22 以来最简单的解决方案。虽然myMap[key] 仍然假定一个字符串键(see FAQ entry why),但现在可以使用myMap?api.get(key) 作为一种解决方法。但它需要一些配置:

首先,?api默认是不允许的,所以你需要将api_builtin_enabledConfiguration.setAPIBuiltinEnabled(boolean))设置为true。 那么,使用的object_wrapperConfiguration.setObjectWrapper(ObjectWrapper))需要支持这个特性(暴露API)。如果您没有在任何地方设置object_wrapper,那么只需将incompatible_improvements 设置(Configuration 构造函数参数或Configuration.setIncompatibleImprovements(Version))增加到 2.3.22 即可解决此问题。如果您设置object_wrapper(即覆盖默认值),并且它是DefaultObjectWrapper 实例,请注意DefaultObjectWrapper 有自己的incompatibleImprovements 属性,必须设置为2.3.22。如果您使用的是纯 BeansWrapper(不推荐!),那么您无需执行任何操作,因为它始终支持此功能。

【讨论】:

【参考方案2】:

在此解释Freemarker Documentation FAQ,

您不能在 myMap[key] 表达式中使用非字符串键。你可以使用方法!

因此,您可以创建一个 bean,为您提供访问 Java EnumMap 的方法(即)。然后只需使用您的 mapp 实例化这个 bean,然后将 bean 放入您的模型中。

class EnumMap

    HashMap<MyEnum, String> map = new HashMap<MyEnum, String>();

    public String getValue(MyEnum e)
    
        return map.get(e);
        
    ..constructor, generics, getters, setters left out.

我对您要实现的总体目标有点困惑。如果您只需要列出枚举的值(或者每个枚举的显示值)。有一种更简单的方法。

我看到解决此问题的一种方法是在 Enum 实例上放置一个显示值。

enum MyEnum 
   FOO("Foo"), 
    BAR_EXAMPLE("Bar Example"); 
    private String displayValue;

    MyEnum(String displayValue)
    
        this.displayValue = displayValue;
    

    public String getDisplay()
    
        return displayValue;
    

这允许您将 Enum 本身放入您的配置中,并遍历所有实例。

SimpleHash globalModel = new SimpleHash();
TemplateHashModel enumModels = BeansWrapper.getDefaultInstance().getEnumModels();
TemplateHashModel myEnumModel = (TemplateHashModel) enumModels.get("your.fully.qualified.enum.MyEnum");

globalModel.put("MyEnum", myEnumModel);
freemarkerConfiguration.setAllSharedVariables(globalModel);

然后就可以遍历枚举了,

<#list MyEnum?values as item>
    $item.display
</#list> 

【讨论】:

但是当我想使用枚举作为键访问地图时,它不起作用。 mymap[MyEnum.SOMETHING] 不起作用是有道理的,但我也不能使用 mymap.get(MyEnum.SOMETHING)! 请注意,这不再是最简单的解决方案了。看我的回答。 @Wouter Lievens: mymap.get() 仅适用于特定的object_wrapper 设置值(纯BeansWrappersimpleMaps=false),但强烈建议不要使用该值,并从根本上更改object_wrapper在现有应用程序下可以很容易地破坏它。无论如何,请参阅我的答案以获得更“便携”的解决方案。

以上是关于Freemarker:如何使用枚举作为键遍历 Map的主要内容,如果未能解决你的问题,请参考以下文章

freemarker如何遍历模板中所有变量

Freemarker如何遍历List<String>集合?

遍历 hastable 键的枚举会引发 NoSuchElementException 错误

在打字稿中使用枚举作为接口键

FreeMarker如何将ACTION传递的数组放入对应数组?

Freemarker 和 hashmap。我如何获得键值