Introduction à Moustache

1. Vue d'ensemble

Dans cet article, nous allons nous concentrer sur les modèles Moustache et utiliser l'une de ses API Java pour produire du contenu HTML dynamique.

Moustache est un moteur de modèle sans logique permettant de créer du contenu dynamique comme du HTML, des fichiers de configuration, entre autres.

2. Présentation

En termes simples, le moteur est classé comme sans logique car il n'a pas de constructions qui prennent en charge les instructions if-else et les boucles for.

Les modèles Moustache se composent de noms de balises entourés de {{}} (qui ressemblent à des moustaches - d'où le nom) et sont soutenus par un objet modèle contenant les données du modèle.

3. Dépendance de Maven

La compilation et l'exécution des modèles sont prises en charge par plusieurs langues - côté client et côté serveur.

Pour pouvoir traiter les modèles à partir de Java, nous utilisons sa bibliothèque Java qui peut être ajoutée en tant que dépendance Maven.

Java 8+:

 com.github.spullara.mustache.java compiler 0.9.4 

Java 6/7:

 com.github.spullara.mustache.java compiler 0.8.18 

Nous pouvons vérifier les dernières versions de la bibliothèque dans le dépôt central de Maven.

4. Utilisation

Regardons un scénario simple qui montre comment:

  1. Rédigez un modèle simple
  2. Compilez le modèle à l'aide de l'API Java
  3. Exécutez-le en fournissant les données nécessaires

4.1. Un modèle de moustache simple

Nous allons créer un modèle simple pour afficher les détails d'une tâche à effectuer:

{{title}}

Created on {{createdOn}}

{{text}}

Dans le modèle ci-dessus, les champs entre les accolades ({{}}) peuvent être:

  • méthodes et propriétés d'une classe Java
  • clés d'un objet Map

4.2. Compilation du modèle Moustache

Nous pouvons compiler le modèle comme indiqué ci-dessous:

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

MoustacheFactory recherche le modèle donné dans le chemin de classe. Dans notre exemple, nous plaçons todo.mustache sous src / main / resources .

4.3. Exécution du modèle Moustache

Les données fournies au modèle seront une instance de la classe Todo dont la définition est:

public class Todo { private String title; private String text; private boolean done; private Date createdOn; private Date completedOn; // constructors, getters and setters }

Le modèle compilé peut être exécuté pour obtenir du HTML comme indiqué ci-dessous:

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

5. Sections et itérations de la moustache

Voyons maintenant comment lister les todos. Pour itérer sur une liste de données, nous utilisons les sections Moustache.

Une section est un bloc de code qui se répète une ou plusieurs fois en fonction de la valeur de la clé dans le contexte courant.

Cela ressemble à quelque chose comme:

{{#todo}}  {{/todo}}

Une section commence par un dièse (#) et se termine par une barre oblique (/), où chacun des signes est suivi de la clé dont la valeur est utilisée comme base pour le rendu de la section.

Voici les scénarios qui peuvent se produire en fonction de la valeur de la clé:

5.1. Section avec liste non vide ou valeur non fausse

Créons un modèle todo-section.mustache qui utilise une section:

{{#todo}} 

{{title}}

Created on {{createdOn}}

{{text}}

{{/todo}}

Regardons ce modèle en action:

@Test public void givenTodoObject_whenGetHtml_thenSuccess() throws IOException { Todo todo = new Todo("Todo 1", "Todo description"); Mustache m = MustacheUtil.getMustacheFactory() .compile("todo.mustache"); Map context = new HashMap(); context.put("todo", todo); String expected = "

Todo 1

"; assertThat(executeTemplate(m, todo)).contains(expected); }

Créons un autre modèle todos.mustache pour lister les todos:

{{#todos}} 

{{title}}

{{/todos}}

Et créez une liste de todos en l'utilisant:

@Test public void givenTodoList_whenGetHtml_thenSuccess() throws IOException { Mustache m = MustacheUtil.getMustacheFactory() .compile("todos.mustache"); List todos = Arrays.asList( new Todo("Todo 1", "Todo description"), new Todo("Todo 2", "Todo description another"), new Todo("Todo 3", "Todo description another") ); Map context = new HashMap(); context.put("todos", todos); assertThat(executeTemplate(m, context)) .contains("

Todo 1

") .contains("

Todo 2

") .contains("

Todo 3

"); }

5.2. Section Avec vide Liste ou False ou nulle valeur

Testons le todo-section.mustache avec une valeur nulle :

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

And likewise, test todos.mustache with an empty list:

@Test public void givenEmptyList_whenGetHtml_thenEmptyHtml() throws IOException { Mustache m = MustacheUtil.getMustacheFactory() .compile("todos.mustache"); Map context = new HashMap(); assertThat(executeTemplate(m, context)).isEmpty();; }

6. Inverted Sections

Inverted sections are those which are rendered only once based on the non-existence of the key or false or null value or an empty list. In other words, these are rendered when a section is not rendered.

These start with a caret (^) and end with a slash (/) as shown below:

{{#todos}} 

{{title}}

{{/todos}} {{^todos}}

No todos!

{{/todos}}

The above template when provided with an empty list:

@Test public void givenEmptyList_whenGetHtmlUsingInvertedSection_thenHtml() throws IOException { Mustache m = MustacheUtil.getMustacheFactory() .compile("todos-inverted-section.mustache"); Map context = new HashMap(); assertThat(executeTemplate(m, context).trim()) .isEqualTo("

No todos!

"); }

7. Lambdas

The values for keys of a mustache section can be a function or a lambda expression. In such case, the complete lambda expression is invoked by passing in the text within the section as a parameter to the lambda expression.

Let's look at a template todos-lambda.mustache:

{{#todos}} 

{{title}}{{#handleDone}}{{doneSince}}{{/handleDone}}

{{/todos}}

La clé handleDone se résout en une expression lambda Java 8 comme indiqué ci-dessous:

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

Le code HTML généré en exécutant le modèle ci-dessus est:

Todo 1

Todo 2

Todo 3Done 5 minutes ago

8. Conclusion

Dans cet article d'introduction, nous avons examiné la création de modèles de moustache avec des sections, des sections inversées et des lambdas. Et nous avons utilisé l'API Java pour compiler et exécuter les modèles en fournissant des données pertinentes.

Il existe quelques fonctionnalités plus avancées de Moustache qui méritent d'être explorées, telles que:

  • fournir un appelable comme valeur qui aboutit à une évaluation simultanée
  • en utilisant DecoratedCollection pour obtenir le premier, le dernier et l'index des éléments de la collection
  • invert API qui donne les données données le texte et le modèle

Et, comme toujours, le code source complet pour cela est disponible sur Github.