Freemarker: как перебирать карту, используя перечисления в качестве ключей - PullRequest
12 голосов
/ 24 марта 2011

Следующий код не работает, поскольку 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 описано, как получить доступ к самому Enum, но я не нашелчто-нибудь о том, как получить значение из хэша, используя Enum в качестве ключа.

Спасибо.

Ответы [ 2 ]

12 голосов
/ 26 марта 2011

Перефразируя Часто задаваемые вопросы по документации Freemarker ,

Нельзя использовать нестроковые ключи в выражении myMap [key].Вы можете использовать методы!

Таким образом, вы можете создать bean-компонент, который предоставит вам способ получить доступ к Java EnumMap (т.е.).Затем просто создайте экземпляр этого bean-компонента с помощью своего mapp и поместите 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> 
4 голосов
/ 01 марта 2015

Принятый ответ - не самое простое решение с 2.3.22. В то время как myMap[key] по-прежнему предполагает использование строкового ключа ( см. Раздел часто задаваемых вопросов, почему ), теперь можно использовать 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. Если вы используете чистый BeansWrapper (не рекомендуется!), Вам ничего не нужно делать, поскольку он всегда поддерживает эту функцию.
...