Einführung in den Schnurrbart

1. Überblick

In diesem Artikel konzentrieren wir uns auf die Mustache -Vorlagen und verwenden eine der Java APIs , um dynamischen HTML-Inhalt zu erstellen .

Moustache ist eine logiklose Vorlagen-Engine zum Erstellen dynamischer Inhalte, wie HTML, Konfigurationsdateien und andere.

2. Einführung

Einfach ausgedrückt, wird die Engine als logicless klassifiziert, da sie keine Konstrukte enthält, die if-else-Anweisungen und for-Schleifen unterstützen.

Die Mustache-Vorlagen bestehen aus Tag-Namen, die von \ {\ {}} umgeben sind (die dem Schnurrbart ähneln - daher der Name). Sie werden von einem Modellobjekt unterstützt, das die Daten für die Vorlage enthält.

3. Maven-Abhängigkeit

Die Erstellung und Ausführung der Vorlagen wird von mehreren Sprachen unterstützt - sowohl auf der Clientseite als auch auf der Serverseite.

Um die Vorlagen von Java aus verarbeiten zu können, verwenden wir die Java-Bibliothek, die als Maven-Abhängigkeit hinzugefügt werden kann.

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>

Wir können die neuesten Versionen der Bibliothek unter https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.github.spullara.mustache.java%22%20AND%20a% überprüfen. 3A% 22compiler% 22[Central Maven Repository].

4. Verwendungszweck

Schauen wir uns ein einfaches Szenario an, das zeigt, wie man:

  1. Schreiben Sie eine einfache Vorlage

  2. Kompilieren Sie die Vorlage mithilfe der Java-API

  3. Führen Sie es aus, indem Sie die erforderlichen Daten angeben

4.1. Eine einfache Schnurrbartvorlage

Wir erstellen eine einfache Vorlage zum Anzeigen der Details einer Aufgabenaufgabe:

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

In der obigen Vorlage können die Felder in den geschweiften Klammern (\ {\ {}}) sein:

  • Methoden und Eigenschaften einer Java-Klasse

  • Schlüssel eines Map -Objekts

4.2. Schnurrbartvorlage kompilieren

Wir können die Vorlage wie folgt zusammenstellen:

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

MustacheFactory sucht im Klassenpfad nach der angegebenen Vorlage. In unserem Beispiel platzieren wir todo.mustache unter src/main/resources .

4.3. Schnurrbart-Vorlage ausführen

Die Daten, die der Vorlage zur Verfügung gestellt werden, sind eine Instanz der Klasse Todo , deren Definition:

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

   //constructors, getters and setters
}

Die kompilierte Vorlage kann ausgeführt werden, um HTML wie unten gezeigt zu erhalten:

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

5. Schnurrbartabschnitte und Iterationen

Schauen wir uns nun an, wie die Aufgaben aufgelistet werden. Für das Durchlaufen von Listendaten verwenden wir Schnurrbartabschnitte.

Ein Abschnitt ist ein Codeblock, der je nach Wert des Schlüssels im aktuellen Kontext ein- oder mehrmals wiederholt wird.

Es sieht ungefähr so ​​aus:

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

Ein Abschnitt beginnt mit einem Pfund (#) und endet mit einem Schrägstrich (/), wobei auf jedes der Zeichen der Schlüssel folgt, dessen Wert als Grundlage für das Rendern des Abschnitts verwendet wird.

Nachfolgend sind die Szenarien aufgeführt, die je nach Wert des Schlüssels auftreten können:

5.1. Abschnitt mit nicht leerer Liste oder nicht falschem Wert

Erstellen Sie eine Vorlage todo-section.mustache , die einen Abschnitt verwendet:

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

Schauen wir uns diese Vorlage in Aktion an:

@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);
}

Erstellen wir eine weitere Vorlage todos.mustache zum Auflisten der Todos:

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

Und erstellen Sie eine Liste von ToDos mit dieser:

@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. Abschnitt mit leerem List - oder False - oder Null -Wert

Testen wir den todo-section.mustache mit einem null -Wert:

@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();
}

Testen Sie todos.mustache ebenfalls mit einer leeren Liste:

@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. Umgekehrte Abschnitte

  • Invertierte Abschnitte sind diejenigen, die nur einmal basierend auf der Nichtexistenz des Schlüssels ** oder des Werts false oder null oder einer leeren Liste gerendert werden.

Mit anderen Worten, diese werden gerendert, wenn ein Abschnitt nicht gerendert wird.

Diese beginnen mit einem Caret (^) und enden mit einem Schrägstrich (/) wie unten gezeigt:

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

Die obige Vorlage, wenn eine leere Liste bereitgestellt wird:

@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. Lambdas

Die Werte für Tasten eines Schnurrbartabschnitts können eine Funktion oder ein Lambda-Ausdruck sein . In diesem Fall wird der vollständige Lambda-Ausdruck aufgerufen, indem der Text innerhalb des Abschnitts als Parameter an den Lambda-Ausdruck übergeben wird.

Schauen wir uns eine Vorlage todos-lambda.mustache an:

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

Der Schlüssel handleDone wird wie folgt in einen Java 8-Lambda-Ausdruck aufgelöst:

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

Der HTML-Code, der durch Ausführen der obigen Vorlage generiert wird, lautet:

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

8. Fazit

In diesem einleitenden Artikel haben wir uns mit dem Erstellen von Schnurrbartvorlagen mit Abschnitten, invertierten Abschnitten und Lambdas beschäftigt. Wir haben die Java-API verwendet, um die Vorlagen durch Bereitstellung relevanter Daten zu kompilieren und auszuführen.

Es gibt einige erweiterte Funktionen von Moustache, die es wert sind, erkundet zu werden - wie zum Beispiel:

  • Bereitstellen eines aufrufbaren als Wert, der zu einem gleichzeitigen Ergebnis führt

Auswertung ** Verwenden von DecoratedCollection , um die erste, letzte und den Index der Sammlung abzurufen

Elemente ** invert API, die die angegebenen Daten mit Text und Vorlage angibt

Und wie immer ist der vollständige Quellcode dafür verfügbar: over auf Github .