Имитация нулевых параметров в макросах Freemarker - PullRequest
12 голосов
/ 02 июля 2011

Я создаю сайт с помощью Freemarker и начал активно использовать макросы. В Freemarker 2.3 я знаю, что передача нулевого значения в макрос в качестве параметра равносильна не передаче параметра вообще, поэтому я создал глобальную переменную с именем «null» для имитации проверки на нуль в моих макросах:

<#assign null="NUL" />

Теперь в моих макросах я могу сделать это:

<#maco doSomething param1=null>
  <#if param1 != null>
    <div>WIN!</div>
  </#if>
</#macro>

Проблема возникает, если я хочу передать параметр, который не является скалярным. Например, передача списка (который в Freemarker является SimpleSequence) макросу и проверка по моему пустому ключевому слову приводит к ошибке:

freemarker.template.TemplateException: Единственные правовые сравнения между два числа, две строки или два даты. Левый операнд является freemarker.template.SimpleSequence Правый операнд является freemarker.template.SimpleScalar

Я посмотрел на код бесплатного маркера и вижу проблему (ComparisonExpression.isTrue ()):

if(ltm instanceof TemplateNumberModel && rtm instanceof TemplateNumberModel) { 
  ...
}
else if(ltm instanceof TemplateDateModel && rtm instanceof TemplateDateModel) {
  ...
}
else if(ltm instanceof TemplateScalarModel && rtm instanceof TemplateScalarModel) {
  ...
}
else if(ltm instanceof TemplateBooleanModel && rtm instanceof TemplateBooleanModel) {
  ...
}
// Here we handle compatibility issues
else if(env.isClassicCompatible()) {
  ...
}
else {
  throw new TemplateException("The only legal comparisons...", env);
}

Таким образом, единственное решение, которое я могу придумать, - установить для isClassicCompatible значение true, которое, я думаю, вызовет toString () для обоих объектов и сравнит результат. Однако в документации конкретно сказано, что все, что зависит от старых функций, должно быть переписано.

Мой вопрос: есть ли решение для этого, которое не полагается на устаревшие функции?

Ответы [ 6 ]

18 голосов
/ 05 июля 2011

Ссылка null является ошибкой во FreeMarker.Определение пользовательского нулевого значения, которое является строкой, не очень хорошая идея по указанным вами причинам.Вместо этого следует использовать следующие конструкции:

  • Параметры макросов и функций могут иметь значение по умолчанию, поэтому вызывающие могут их опустить
  • Чтобы проверить, является ли переменная null,следует использовать оператор ??: <#if (name??)>
  • Когда вы используете переменную, которая может быть null, вы должны использовать оператор !, чтобы указать значение по умолчанию: name!"No name"
  • Чтобы проверить, является ли последовательность (или строка) пустой, используйте встроенную команду ?has_content: <#if (names?has_content)>

Вы можете указать пустую последовательность в качестве значения параметра по умолчанию в макросе и простопроверить, пусто ли оно.

9 голосов
/ 24 сентября 2012

Вот что я сделал, что, похоже, работает в большинстве сценариев:

Значением по умолчанию должна быть пустая строка , а проверка на ноль должна быть ? Has_content .

<#macro someMacro optionalParam="" >
    <#if (optionalParam?has_content)>
        <#-- NOT NULL -->
    <#else>
        <#-- NULL -->
    </#if>
</#macro>
3 голосов
/ 06 июля 2011

Сотрудник предположил, что функция проверки на нуль может быть самым элегантным решением:

<#assign null="NUL" />

<#function is_null variable>
  <#if variable?is_string & variable == null>
    <#return true />
  <#else>
    <#return false />
  </#if>
</#function>

Работая с этой идеей, я нашел другое возможное решение в списке рассылки , которыйявляется создание функции проверки на нуль в Java путем расширения TemplateMethodModelEx.Затем я могу вставить его непосредственно в карту модели и сделать его доступным во всех моих шаблонах.Полученный код Freemarker довольно чистый:

<#maco doSomething param1=null>
  <#if !is_null(param1)>
    <div>WIN!</div>
  </#if>
</#macro>

Похоже, это лучший способ симулировать нулевые параметры внутри макроса.

1 голос
/ 08 мая 2017

Это еще одно решение, которое может соответствовать вашим потребностям.

<#macro el user={}>
...
<input type="text" class="form-control" name="firstName"
                                       value="${(user.identity.firstName)!''}">
...
</#macro>

Я определяю пустой объект по умолчанию {} вместо нуля, чтобы избежать 2 больших блоков if в моем элементе.

убедитесь, что когда вы задаете значение по умолчанию для атрибута (firstName в моем случае), поместите скобки во все выражения, а затем!знак.

Так что, если identity не определено или firstName не определено, freemarker использует значение по умолчанию

(user.identity.firstName)!''
1 голос
/ 08 июля 2011

Вы можете проверить, если это не скаляр сначала:

<#if !param1?is_scalar || param1 != null)>
0 голосов
/ 16 августа 2018

На самом деле я не понимаю, почему ноль не допускаются.У меня есть Java-функция для получения определенного URL изображения с заданными необязательными / обнуляемыми параметрами, такими как height .

Я написал для него макрос, используя следующий обходной путь:

Java-функция

/**
 * Converts the given value to <code>null</code> if it equals the default
 * value, else returns it directly.
 *
 * @param value
 * @param defaultValue
 *
 * @return
 */
public static Object nullIfDefault(final Object value, final Object defaultValue)
{
    if (value != null && value.equals(defaultValue))
        return null;
    return value;
}

/**
 * Converts the given value to <code>null</code> if it equals an empty
 * string, else returns it directly.
 *
 * @param value
 *
 * @return
 */
public static Object nullIfEmpty(final Object value)
{
    return ObjectUtils.nullIfDefault(value, "");
}

Макрос

Импорт статической функции

<#assign ObjectUtils=statics['com.example.ObjectUtils']/>

<#macro compEntityImage imageRetriever entity height="" width="">

    <img src="${imageRetriever.getMediaFileUrl(entity, 
        ObjectUtils.nullIfEmpty(height), 
        ObjectUtils.nullIfEmpty(width))}">

</#macro>

Разметка

<@compEntityImgage imageRetriever=imageRetriver entity=product height=500/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...