1. Panoramica
In questo articolo, ci concentreremo sui modelli Moustache e utilizzeremo una delle sue API Java per produrre contenuto HTML dinamico.
Moustache è un motore di modelli senza logica per la creazione di contenuti dinamici come HTML, file di configurazione tra le altre cose.
2. Introduzione
In poche parole, il motore è classificato come senza logica perché non ha costrutti che supportano istruzioni if-else e cicli for.
I modelli Moustache sono costituiti da nomi di tag circondati da {{}} (che assomigliano a baffi, da cui il nome) e sono supportati da un oggetto modello contenente i dati per il modello.
3. Dipendenza da Maven
La compilazione e l'esecuzione dei modelli sono supportate da più lingue, sia lato client che lato server.
Per poter elaborare i template da Java utilizziamo la sua libreria Java che può essere aggiunta come dipendenza Maven.
Java 8+:
com.github.spullara.mustache.java compiler 0.9.4
Java 6/7:
com.github.spullara.mustache.java compiler 0.8.18
Possiamo controllare le ultime versioni della libreria nel Central Maven Repository.
4. Utilizzo
Diamo un'occhiata a un semplice scenario che mostra come:
- Scrivi un semplice modello
- Compila il modello utilizzando l'API Java
- Eseguilo fornendo i dati necessari
4.1. Un semplice modello di baffi
Creeremo un semplice modello per visualizzare i dettagli di un'attività da fare:
{{title}}
Created on {{createdOn}} {{text}}
Nel modello sopra i campi all'interno delle parentesi graffe ({{}}) possono essere:
- metodi e proprietà di una classe Java
- chiavi di un oggetto Map
4.2. Compilazione del modello di baffi
Possiamo compilare il modello come mostrato di seguito:
MustacheFactory mf = new DefaultMustacheFactory(); Mustache m = mf.compile("todo.mustache");
MoustacheFactory cerca il modello dato nel classpath. Nel nostro esempio, mettiamo todo.mustache in src / main / resources .
4.3. Esecuzione del modello di baffi
I dati forniti al modello saranno un'istanza della classe Todo la cui definizione è:
public class Todo { private String title; private String text; private boolean done; private Date createdOn; private Date completedOn; // constructors, getters and setters }
Il modello compilato può essere eseguito per ottenere HTML come mostrato di seguito:
Todo todo = new Todo("Todo 1", "Description"); StringWriter writer = new StringWriter(); m.execute(writer, todo).flush(); String html = writer.toString();
5. Sezioni e iterazioni dei baffi
Diamo ora uno sguardo a come elencare le cose da fare. Per l'iterazione dei dati di una lista, utilizziamo le sezioni Moustache.
Una sezione è un blocco di codice che viene ripetuto una o più volte a seconda del valore della chiave nel contesto corrente.
Assomiglia a:
{{#todo}} {{/todo}}
Una sezione inizia con un cancelletto (#) e termina con una barra (/), dove ciascuno dei segni è seguito dalla chiave il cui valore viene utilizzato come base per il rendering della sezione.
Di seguito sono riportati gli scenari che possono verificarsi a seconda del valore della chiave:
5.1. Sezione con elenco non vuoto o valore non falso
Creiamo un modello todo-section.mustache che utilizza una sezione:
{{#todo}} {{title}}
Created on {{createdOn}} {{text}}
{{/todo}}
Diamo un'occhiata a questo modello in azione:
@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); }
Creiamo un altro modello todos.mustache per elencare i todos:
{{#todos}} {{title}}
{{/todos}}
E crea un elenco di cose da fare usandolo:
@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. Sezione Con Vuoto List o False o Null Valore
Testiamo la todo-section.mustache con un valore nullo :
@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 chiave handleDone si risolve in un'espressione lambda Java 8 come mostrato di seguito:
public Function handleDone() { return (obj) -> done ? String.format("Done %s minutes ago", obj) : ""; }
L'HTML generato eseguendo il modello sopra è:
Todo 1
Todo 2
Todo 3Done 5 minutes ago
8. Conclusione
In questo articolo introduttivo, abbiamo esaminato la creazione di modelli di baffi con sezioni, sezioni invertite e lambda. E abbiamo utilizzato l'API Java per compilare ed eseguire i modelli fornendo dati rilevanti.
Ci sono alcune funzionalità più avanzate di Moustache che vale la pena esplorare, come:
- fornendo un callable come valore che si traduce in una valutazione simultanea
- utilizzando DecoratedCollection per ottenere il primo, l'ultimo e l'indice degli elementi della raccolta
- invert API che fornisce i dati forniti dal testo e dal modello
E, come sempre, il codice sorgente completo per questo è disponibile su Github.