问题
The following code does not work because Freemarker seems to cast the value of the expression inside [] to String and then to use it as a key, which is not what is actually expected.
Preparing a template model:
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>
In the Freemarker documentation it is described how to access the Enum itself, but I didn't find anything about how to get a value from a hash using Enum as a key.
Thank you.
回答1:
To paraphrase Freemarker Documentation FAQ on this,
You can't use non-string keys in the myMap[key] expression. You can use methods!
So, you could create a bean that provides a way for you to get to your Java EnumMap, (i.e). Then just instantiate this bean with your mapp, and put the bean in your Model.
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.
}
I'm a little bit confused about what general goal your trying to accomplish. If you just need to list out the values of the enum (or perhaps a display value for each one). There is a much easier way to do it.
One way I've seen this problem solved is by putting a display value on the Enum instances.
i.e
enum MyEnum
{ FOO("Foo"),
BAR_EXAMPLE("Bar Example");
private String displayValue;
MyEnum(String displayValue)
{
this.displayValue = displayValue;
}
public String getDisplay()
{
return displayValue;
}
}
This allows you to put the Enum itself into your configuration, and iterate over all instances.
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);
Then you can iterate over the enum,
<#list MyEnum?values as item>
${item.display}
</#list>
回答2:
The accepted answer isn't the simplest solution since 2.3.22. While myMap[key]
still assumes a string key (see FAQ entry why), now one can use myMap?api.get(key)
as a workaround. It needs some configuring though:
- First of all,
?api
is disallowed by default, so you need to set theapi_builtin_enabled
(Configuration.setAPIBuiltinEnabled(boolean)
) setting totrue
. - Then, the
object_wrapper
(Configuration.setObjectWrapper(ObjectWrapper)
) used needs to support this feature (exposing the API). If you don't set theobject_wrapper
anywhere, then just increasing theincompatible_improvements
setting (theConfiguration
constructor parameter, orConfiguration.setIncompatibleImprovements(Version)
) to 2.3.22 solves this. If you set theobject_wrapper
(i.e., you overwrite the default), and it's aDefaultObjectWrapper
instance, then note thatDefaultObjectWrapper
has its ownincompatibleImprovements
property that has to be set to 2.3.22. If you are using pureBeansWrapper
(not recommended!) then you have to do nothing, as it always supports this feature.
来源:https://stackoverflow.com/questions/5422412/freemarker-how-to-iterate-through-the-map-using-enums-as-keys