Freemarker:如何使用枚举作为键来迭代Map

时间:2011-03-24 16:29:53

标签: java enums map key freemarker

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

准备模板模型:

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

my.ftl:

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

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

谢谢。

2 个答案:

答案 0 :(得分:12)

在此上解释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> 

答案 1 :(得分:4)

接受的答案不是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(不推荐!),那么您必须不做任何事情,因为它始终支持此功能。