Freemarker: как перебирать карту, используя перечисления в качестве ключей
следующий код не работает, потому что Freemarker, похоже, передает значение выражения внутри [] в строку, а затем использует его в качестве ключа, что на самом деле не ожидается.
подготовка модели шаблона:
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 описано, как получить доступ к самому перечислению, но я ничего не нашел о том, как получить значение из хэша, используя перечисление в качестве ключ.
спасибо.
2 ответов
перефразируя Freemarker документация FAQ на этой
вы не можете использовать нестроковые ключи в выражении myMap[key]. Вы можете использовать методы!
таким образом, вы можете создать боб, который предоставляет вам способ добраться до вашего Java EnumMap, (i.e). Затем просто создайте экземпляр этого компонента с помощью mapp и поместите его в свою модель.
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 MyEnum
{ FOO("Foo"),
BAR_EXAMPLE("Bar Example");
private String displayValue;
MyEnum(String displayValue)
{
this.displayValue = displayValue;
}
public String getDisplay()
{
return displayValue;
}
}
Это позволяет поместить перечисление в вашу конфигурацию и выполнить итерацию по всем экземплярам.
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>
принятый ответ не является самым простым решением с 2.3.22. В то время как myMap[key]
по-прежнему предполагает ключевую строку (см FAQ Запись Почему), теперь можно использовать myMap?api.get(key)
как временное решение. Она нуждается в некоторой настройке:
- прежде всего,
?api
по умолчанию запрещено, поэтому вам нужно установитьapi_builtin_enabled
(Configuration.setAPIBuiltinEnabled(boolean)
) параметрtrue
. - затем
object_wrapper
(Configuration.setObjectWrapper(ObjectWrapper)
) используется должен поддерживать эту функцию (подвергая API). Если вы не установитеobject_wrapper
в любом месте, а затем просто увеличиваяincompatible_improvements
установки (Configuration
параметр конструктора, илиConfiguration.setIncompatibleImprovements(Version)
) до 2.3.22 решает это. Если вы установитеobject_wrapper
(т. е. вы перезаписываете значение по умолчанию), и этоDefaultObjectWrapper
экземпляр, тогда обратите внимание, чтоDefaultObjectWrapper
свояincompatibleImprovements
свойство, которое должно быть установлено на 2.3.22. Если вы используете pureBeansWrapper
(не рекомендуется!) тогда вам ничего не нужно делать, так как он всегда поддерживает эту функцию.