Введение в усы

1. Обзор

В этой статье мы сосредоточимся на шаблонах Mustache и будем использовать один из его Java APIs для создания динамического содержимого HTML. ,

Mustache - это не имеющий логики шаблонизатор для создания динамического контента , такого как HTML, файлы конфигурации и другие.

2. Вступление

Проще говоря, механизм классифицируется как logicless , потому что у него нет конструкций, поддерживающих операторы if-else и циклы.

Шаблоны усов состоят из имен тегов, окруженных \ {\ {}} (которые напоминают усы - отсюда и название), и поддерживаются объектом модели, содержащим данные для шаблона.

3. Maven Dependency

Компиляция и выполнение шаблонов поддерживаются несколькими языками - как на стороне клиента, так и на стороне сервера.

Чтобы иметь возможность обрабатывать шаблоны из Java, мы используем его библиотеку Java, которая может быть добавлена ​​как зависимость Maven.

Java 8:

<dependency>
    <groupId>com.github.spullara.mustache.java</groupId>
    <artifactId>compiler</artifactId>
    <version>0.9.4</version>
</dependency>

Java 6/7:

<dependency>
    <groupId>com.github.spullara.mustache.java</groupId>
    <artifactId>compiler</artifactId>
    <version>0.8.18</version>
</dependency>

Мы можем проверить последние версии библиотеки в https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.github.spullara.mustache.java%22%20AND%20a% 3A% 22компилятор% 22[Центральное хранилище Maven].

4. Использование

Давайте посмотрим на простой сценарий, который показывает, как:

, Написать простой шаблон

, Скомпилируйте шаблон с помощью Java API

, Выполните его, предоставив необходимые данные

4.1. Простой шаблон усов

Мы собираемся создать простой шаблон для отображения деталей задачи todo:

<h2>{{title}}</h2>
<small>Created on {{createdOn}}</small>
<p>{{text}}</p>

В приведенном выше шаблоне поля в фигурных скобках (\ {\ {}}) могут быть:

  • методы и свойства Java-класса

  • ключи объекта Map

4.2. Составление шаблона усов

Мы можем скомпилировать шаблон, как показано ниже:

MustacheFactory mf = new DefaultMustacheFactory();
Mustache m = mf.compile("todo.mustache");

MustacheFactory ищет указанный шаблон в пути к классам. В нашем примере мы помещаем todo.mustache в src/main/resources .

4.3. Выполнение шаблона усов

Данные, предоставленные шаблону, будут экземпляром класса Todo , определение которого:

public class Todo {
    private String title;
    private String text;
    private boolean done;
    private Date createdOn;
    private Date completedOn;

   //constructors, getters and setters
}

Скомпилированный шаблон может быть выполнен для получения HTML, как показано ниже:

Todo todo = new Todo("Todo 1", "Description");
StringWriter writer = new StringWriter();
m.execute(writer, todo).flush();
String html = writer.toString();

5. Разделы усов и итерации

Давайте теперь посмотрим, как составить список задач. Для перебора данных списка мы используем разделы Усов.

Раздел - это блок кода, который повторяется один или несколько раз в зависимости от значения ключа в текущем контексте.

Это выглядит примерно так:

{{#todo}}
<!-- Other code -->
{{/todo}}

Раздел начинается с фунта (#) и заканчивается косой чертой (/), где за каждым из знаков следует ключ, значение которого используется в качестве основы для рендеринга раздела.

Ниже приведены сценарии, которые могут возникнуть в зависимости от значения ключа:

5.1. Раздел с непустым списком или непустым значением

Давайте создадим шаблон todo-section.mustache , который использует раздел:

{{#todo}}
<h2>{{title}}</h2>
<small>Created on {{createdOn}}</small>
<p>{{text}}</p>
{{/todo}}

Давайте посмотрим на этот шаблон в действии:

@Test
public void givenTodoObject__whenGetHtml__thenSuccess()
  throws IOException {

    Todo todo = new Todo("Todo 1", "Todo description");
    Mustache m = MustacheUtil.getMustacheFactory()
      .compile("todo.mustache");
    Map<String, Object> context = new HashMap<>();
    context.put("todo", todo);

    String expected = "<h2>Todo 1</h2>";
    assertThat(executeTemplate(m, todo)).contains(expected);
}

Давайте создадим еще один шаблон todos.mustache для перечисления задач:

{{#todos}}
<h2>{{title}}</h2>
{{/todos}}

И создайте список задач, используя его:

@Test
public void givenTodoList__whenGetHtml__thenSuccess()
  throws IOException {

    Mustache m = MustacheUtil.getMustacheFactory()
      .compile("todos.mustache");

    List<Todo> todos = Arrays.asList(
      new Todo("Todo 1", "Todo description"),
      new Todo("Todo 2", "Todo description another"),
      new Todo("Todo 3", "Todo description another")
    );
    Map<String, Object> context = new HashMap<>();
    context.put("todos", todos);

    assertThat(executeTemplate(m, context))
      .contains("<h2>Todo 1</h2>")
      .contains("<h2>Todo 2</h2>")
      .contains("<h2>Todo 3</h2>");
}

5.2. Раздел с пустым List или False или Null Value

Давайте проверим todo-section.mustache со значением null :

@Test
public void givenNullTodoObject__whenGetHtml__thenEmptyHtml()
  throws IOException {
    Mustache m = MustacheUtil.getMustacheFactory()
      .compile("todo-section.mustache");
    Map<String, Object> context = new HashMap<>();
    assertThat(executeTemplate(m, context)).isEmpty();
}

И аналогично, протестируйте todos.mustache с пустым списком:

@Test
public void givenEmptyList__whenGetHtml__thenEmptyHtml()
  throws IOException {
    Mustache m = MustacheUtil.getMustacheFactory()
      .compile("todos.mustache");

    Map<String, Object> context = new HashMap<>();
    assertThat(executeTemplate(m, context)).isEmpty();;
}

6. Перевернутые секции

  • Инвертированные разделы - это те, которые отображаются только один раз на основании отсутствия ** ключа или значения false или null или пустого списка.

Другими словами, они отображаются, когда раздел не отображается.

Они начинаются с каретки (^) и заканчиваются косой чертой (/), как показано ниже:

{{#todos}}
<h2>{{title}}</h2>
{{/todos}}
{{^todos}}
<p>No todos!</p>
{{/todos}}

Приведенный выше шаблон предоставляется с пустым списком:

@Test
public void givenEmptyList__whenGetHtmlUsingInvertedSection__thenHtml()
  throws IOException {

    Mustache m = MustacheUtil.getMustacheFactory()
      .compile("todos-inverted-section.mustache");

    Map<String, Object> context = new HashMap<>();
    assertThat(executeTemplate(m, context).trim())
      .isEqualTo("<p>No todos!</p>");
}

7. Лямбда

Значения для ключей в разделе усов могут быть функцией или лямбда-выражением . В таком случае полное лямбда-выражение вызывается передачей текста в разделе в качестве параметра к лямбда-выражению.

Давайте посмотрим на шаблон todos-lambda.mustache :

{{#todos}}
<h2>{{title}}{{#handleDone}}{{doneSince}}{{/handleDone}}</h2>
{{/todos}}

Ключ handleDone преобразуется в лямбда-выражение Java 8, как показано ниже:

public Function<Object, Object> handleDone() {
    return (obj) -> done ?
      String.format("<small>Done %s minutes ago<small>", obj) : "";
}

HTML-код, сгенерированный путем выполнения вышеуказанного шаблона:

<h2>Todo 1</h2>
<h2>Todo 2</h2>
<h2>Todo 3<small>Done 5 minutes ago<small></h2>

8. Заключение

В этой вводной статье мы рассмотрели создание шаблонов усов с разделами, перевернутыми разделами и лямбдами. И мы использовали Java API для компиляции и выполнения шаблонов, предоставляя соответствующие данные.

Есть несколько более продвинутых функций Усов, которые стоит изучить, таких как:

  • предоставление вызываемого в качестве значения, которое приводит к одновременному

оценка ** используя DecoratedCollection , чтобы получить первый, последний и индекс коллекции

элементы ** invert API, который предоставляет данные с учетом текста и шаблона

И, как всегда, полный исходный код для этого доступен over на Github .