Статьи

Шаблонирование с рокером

В этой статье мы кратко рассмотрим Rocker , статически типизированный и быстрый шаблонизатор Java 8.

Требуемые зависимости

Чтобы начать работать с Rocker, нам нужно добавить следующие зависимости в наш проект:

01
02
03
04
05
06
07
08
09
10
11
12
<dependency>
  <groupId>com.fizzed</groupId>
  <artifactId>rocker-runtime</artifactId>
  <version>0.24.0</version>
</dependency>
 
<!-- for hot-reloading support in development -->
<dependency>
  <groupId>com.fizzed</groupId>
  <artifactId>rocker-compiler</artifactId>
  <version>0.24.0</version>
</dependency>

Нам также нужен плагин Rocker Maven, который преобразует шаблоны Rocker в код Java:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<build>
  <plugins>
    <plugin>
      <groupId>com.fizzed</groupId>
      <artifactId>rocker-maven-plugin</artifactId>
      <version>0.24.0</version>
      <executions>
        <execution>
          <id>generate-rocker-templates</id>
          <phase>generate-sources</phase>
          <goals>
            <goal>generate</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Создание первых шаблонов

Мы начнем с простого примера, содержащего два шаблона Rocker и класс Java.

В первом шаблоне ( main.rocker.html ) мы определяем базовую структуру страницы:

01
02
03
04
05
06
07
08
09
10
@args (String title, RockerBody content)
 
<html>
  <head>
    <title>@title</title>
  </head>
  <body>
    @content
  </body>
</html>

Этот шаблон имеет два параметра: заголовок страницы и элемент RockerBody с именем content. Параметр содержимого в основном является суб-шаблоном, который добавляется к тегу <body>.

Теперь мы создаем еще один шаблон ( basic.rocker.html ), который определяет содержимое, которое передается нашему первому шаблону:

1
2
3
4
5
@args (String name)
 
@views.main.template("Basic example") -> {
  <h1>Hello @name!</h1>
}

Этот шаблон имеет единственный параметр имени, который записывается в тег <h1>. Мы ссылаемся на первый шаблон ( main.rocker.html ) с помощью @ views.main и используем метод template (..) для его визуализации. «Основной пример» будет передан в качестве параметра заголовка. Параметр содержимого определен в фигурных скобках.

Рендеринг шаблонов Rocker

Шаблоны Rocker преобразуются в код Java. Это можно сделать с помощью следующей команды Maven:

1
mvn generate-sources

Это создает класс Java для каждого шаблона в каталоге target / generate-sources / rocker .

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public class Main {
 
  public static void main(String... args) throws Exception {
 
    // The template "basic.rocker.html" got converted to the class named "basic"
    // which is located in the "views" package
     
    String result = views.basic.template("John")
        .render()
        .toString();
 
    System.out.println(result);
  }
}

Вывод, который мы получаем, выглядит следующим образом:

1
2
3
4
5
6
7
8
<html>
  <head>
    <title>Basic example</title>
  </head>
  <body>
    <h1>Hello John!</h1>
  </body>
</html>

Немного проблем с этим подходом заключается в том, что вам нужно запускать mvn generate-sources каждый раз, когда вы вносите изменения в файлы шаблона. Также обратите внимание, что ваш Java-код может не скомпилироваться, если генерация кода не удалась, поскольку у вас есть проблема в одном из ваших шаблонов.

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

В этом случае код Java выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public class Main {
 
  public static void main(String... args) throws Exception {
 
    // Enable hot reloading
    RockerRuntime.getInstance().setReloading(true);
 
    // Reference via string instead of using generated code
    String result = Rocker.template("views/basic.rocker.html")
        .bind("name""John")
        .render()
        .toString();
 
    System.out.println(result)
  }
}

Результат, который мы получаем, точно такой же.

Выражения

Предположим, у нас есть простой класс User, который содержит методы getFirstName () и getLastName (). В следующем примере мы видим, как мы можем работать с объектом User в шаблоне Rocker:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@import com.mscharhag.rockerexample.*
 
@args (User user)
 
@views.main.template("Expressions") -> {
  <ul>
    <!-- first name -->
    <li>@user.getFirstName()</li>
 
    <!-- first three letters of first name -->
    <li>@user.getFirstName().substring(0, 3)</li>
 
    <!-- first name and last name -->
    <li>@user.getFirstName() @user.getLastName()</li>
 
    <!-- using a variable-->
    @name => {
      @user.getFirstName() @user.getLastName()
    }
    <li>@name</li>
 
  </ul>
}

условия

Rocker поддерживает стандартную структуру потока Java if-else, как показано в следующем примере:

01
02
03
04
05
06
07
08
09
10
11
@import com.mscharhag.rockerexample.*
 
@args (User user)
 
@views.main.template("Conditions") -> {
  @if (user.getFirstName().length() > 10) {
    <p>Long first name</p>
  } else {
    <p>short first name</p>
  }
}

Loops

Шаблоны Rocker поддерживают различные формы петель:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@import com.mscharhag.rockerexample.*
@import java.util.*
 
@args (List<User> users)
 
@views.main.template("Loops") -> {
  <ul>
    <!-- standard for loop -->
    @for (int i = 0; i < users.size(); i++) {
      <li>@users.get(i).getFirstName()</li>
    }
   
    <!-- standard 'for each' loop -->
    @for (User user : users) {
      <li>@user.getFirstName()</li>
    }
   
    <!-- for each loop with additional loop information
   
      <li>0: John, first: true, last: false</li>
      <li>1: Martin, first: false, last: false</li>
      <li>2: Anna, first: false, last: true</li>
    -->
    @for ((i, user) : users) {
      <li>@i.index(): @user.getFirstName(), first: @i.first(), last: @i.last()</li>
    }
   
  </ul>
}

Последний цикл является специальным вариантом цикла Java для каждого. Второй индексный параметр (названный i в примере) может использоваться для доступа к текущей информации итерации.

Вывод

Rocker может быть опцией, если вы ищете шаблонизатор Java. В соответствии с тестом хранилища Rocker GitHub, Rocker намного быстрее, чем другие движки шаблонов Java, такие как Freemarker или Velocity. Подробная документация — еще один хороший момент для упоминания.

Тот факт, что Rocker компилируется в Java и позволяет передавать данные представлениям безопасным способом, довольно интересен. С одной стороны, это полезно, потому что помогает уменьшить количество ошибок. С другой стороны, эта функция немного раздражала меня, когда я писал примеры. Всякий раз, когда я вносил изменения в код, которые влияли на шаблоны Rocker (например, изменяя имя метода, вызванного в шаблоне Rocker), шаблоны перестали компилироваться. В некоторых ситуациях это снова остановило компиляцию моего Java-кода (потому что он использовал классы, сгенерированные Rocker). Это ожидается, но это может нарушить мой предпочтительный рабочий процесс — сначала писать код Java, а потом исправлять шаблоны. Ссылка на шаблоны через имена файлов вместо использования сгенерированных классов решила эту проблему (но также отбрасывает проверку типов во время компиляции).

Опубликовано на Java Code Geeks с разрешения Михаэля Шаргага, партнера нашей программы JCG. Смотрите оригинальную статью здесь: Шаблонирование с помощью Rocker

Мнения, высказанные участниками Java Code Geeks, являются их собственными.