«1. Обзор

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

Это шаблонизатор без логики для создания динамического контента, который популярен благодаря своей простоте.

Если вы хотите узнать об основах, ознакомьтесь с нашей статьей «Введение в усы».

2. Зависимость Maven

Чтобы иметь возможность использовать Mustache вместе с Spring Boot, нам нужно добавить специальный стартер Spring Boot в наш pom.xml:

<dependency>			
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mustache</artifactId>
</dependency>
<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency>

Кроме того, нам нужен spring- boot-starter-веб-зависимость.

3. Создание шаблонов

Давайте покажем пример и создадим простое приложение MVC с использованием Spring-Boot, которое будет обслуживать статьи на веб-странице.

Давайте напишем первый шаблон для содержания статьи:

<div class="starter-template">
    {{#articles}}
    <h1>{{title}}</h1>
    <h3>{{publishDate}}</h3>
    <h3>{{author}}</h3>
    <p>{{body}}</p>
    {{/articles}}
</div>

Мы сохраним этот файл HTML, скажем, article.html, и сошлемся на него в нашем index.html:

<div class="container">
    {{>layout/article}}
</div>

Здесь layout — это подкаталог, а article — это имя файла шаблона.

Обратите внимание, что расширение файла шаблона усов по умолчанию теперь .mustache. Мы можем переопределить эту конфигурацию с помощью свойства:

spring.mustache.suffix:.html

4. Контроллер

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

@GetMapping("/article")
public ModelAndView displayArticle(Map<String, Object> model) {

    List<Article> articles = IntStream.range(0, 10)
      .mapToObj(i -> generateArticle("Article Title " + i))
      .collect(Collectors.toList());

    model.put("articles", articles);

    return new ModelAndView("index", model);
}

Контроллер возвращает список статей, которые должны отображаться на странице. В шаблоне статьи тег статьи, начинающийся с # и заканчивающийся на /, отвечает за список.

Это будет перебирать переданную модель и отображать каждый элемент отдельно, как в HTML-таблице:

 {{#articles}}...{{/articles}}

Метод generateArticle() создает экземпляр статьи с некоторыми случайными данными.

Обратите внимание, что ключи в модели статьи, возвращаемые контроллером, должны совпадать с ключами тегов шаблона статьи.

Теперь давайте протестируем наше приложение:

@Test
public void givenIndexPage_whenContainsArticle_thenTrue() {

    ResponseEntity<String> entity 
      = this.restTemplate.getForEntity("/article", String.class);
 
    assertTrue(entity.getStatusCode()
      .equals(HttpStatus.OK));
    assertTrue(entity.getBody()
      .contains("Article Title 0"));
}

Мы также можем протестировать приложение, развернув его с помощью:

mvn spring-boot:run

После развертывания мы можем нажать localhost:8080/article, и мы получим наши статьи перечислены:

5. Обработка значений по умолчанию

В среде Mustache, если мы не укажем значение для заполнителя, будет выдано исключение MustacheException с сообщением «Нет метода или поля с именем — переменная». -имя …†.

Во избежание таких ошибок лучше указать глобальное значение по умолчанию для всех заполнителей:

@Bean
public Mustache.Compiler mustacheCompiler(
  Mustache.TemplateLoader templateLoader, 
  Environment environment) {

    MustacheEnvironmentCollector collector
      = new MustacheEnvironmentCollector();
    collector.setEnvironment(environment);

    return Mustache.compiler()
      .defaultValue("Some Default Value")
      .withLoader(templateLoader)
      .withCollector(collector);
}

6. Усы с Spring MVC

Теперь давайте обсудим, как интегрироваться со Spring MVC, если мы решим не использовать Spring Boot. Во-первых, добавим зависимость:

<dependency>
    <groupId>com.github.sps.mustache</groupId>
    <artifactId>mustache-spring-view</artifactId>
    <version>1.4</version>
</dependency>

Последние можно найти здесь.

Далее нам нужно настроить MustacheViewResolver вместо Spring InternalResourceViewResolver:

@Bean
public ViewResolver getViewResolver(ResourceLoader resourceLoader) {
    MustacheViewResolver mustacheViewResolver
      = new MustacheViewResolver();
    mustacheViewResolver.setPrefix("/WEB-INF/views/");
    mustacheViewResolver.setSuffix("..mustache");
    mustacheViewResolver.setCache(false);
    MustacheTemplateLoader mustacheTemplateLoader 
      = new MustacheTemplateLoader();
    mustacheTemplateLoader.setResourceLoader(resourceLoader);
    mustacheViewResolver.setTemplateLoader(mustacheTemplateLoader);
    return mustacheViewResolver;
}

Нам просто нужно настроить суффикс, где хранятся наши шаблоны, префикс расширения наших шаблонов и templateLoader, который будет отвечать для загрузки шаблонов.

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

В этом кратком руководстве мы рассмотрели использование шаблонов Mustache с Spring Boot, отрисовку набора элементов в пользовательском интерфейсе, а также предоставление значений по умолчанию для переменных, чтобы избежать ошибок.

Наконец, мы обсудили, как интегрировать его со Spring, используя MustacheViewResolver.

Как всегда, исходный код доступен на GitHub.