1. Overview
1.概述
In this article, we’ll focus on Mustache templates and use one of its Java APIs for producing dynamic HTML content.
在本文中,我们将关注Mustache模板,并使用其Java API中的一个来制作动态HTML内容。
Mustache is a logicless template engine for creating dynamic content like HTML, configuration files among other things.
Mustache是一个无逻辑的模板引擎,用于创建动态内容,如HTML、配置文件等。
2. Introduction
2.简介
Simply put, the engine is classified as logicless because it doesn’t have constructs that support if-else statements and for loops.
简单地说,该引擎被归类为无逻辑,因为它没有支持if-else语句和for循环的结构。
The Mustache templates consist of tag names surrounded by { { } } (which resemble mustaches – hence the name) and are backed by a model object containing the data for the template.
小胡子模板由标签名称组成,周围有{ { } }(类似于小胡子–因此得名),并由一个包含模板数据的模型对象支持。}(类似于胡子–因此得名),并由一个包含模板数据的模型对象支持。
3. Maven Dependency
3.Maven的依赖性
Compilation and execution of the templates are supported by multiple languages – both client side and server side.
模板的编译和执行是由多种语言支持的–包括客户端和服务器端。
To be able to process the templates from Java we make use of its Java library which can be added as a Maven dependency.
为了能够从Java中处理模板,我们利用了其Java库,该库可以作为Maven的依赖项加入。
Java 8+:
Java 8以上。
<dependency>
<groupId>com.github.spullara.mustache.java</groupId>
<artifactId>compiler</artifactId>
<version>0.9.4</version>
</dependency>
Java 6/7:
Java 6/7。
<dependency>
<groupId>com.github.spullara.mustache.java</groupId>
<artifactId>compiler</artifactId>
<version>0.8.18</version>
</dependency>
We can check the latest versions of the library in the Central Maven Repository.
我们可以在Central Maven Repository中查看该库的最新版本。
4. Usage
4.使用方法
Let’s look at a simple scenario which shows how to:
让我们看一下一个简单的场景,它显示了如何。
- Write a simple template
- Compile the template using Java API
- Execute it by providing the necessary data
4.1. A Simple Mustache Template
4.1.一个简单的小胡子模板
We’re going to create a simple template for displaying the details of a todo task:
我们将创建一个简单的模板,用于显示一项待办事项的细节。
<h2>{{title}}</h2>
<small>Created on {{createdOn}}</small>
<p>{{text}}</p>
In the above template the fields within the curly braces ({{}}) can be:
在上述模板中,大括号({{}})内的字段可以是。
- methods and properties of a Java class
- keys of a Map object
4.2. Compiling the Mustache Template
4.2.编译Mustache模板
We can compile the template as shown below:
我们可以按照下面的方式编译模板。
MustacheFactory mf = new DefaultMustacheFactory();
Mustache m = mf.compile("todo.mustache");
MustacheFactory searches for the given template in the classpath. In our example, we place todo.mustache under src/main/resources.
MustacheFactory在classpath中搜索指定的模板。在我们的例子中,我们把todo.mustache放在src/main/resources下。
4.3. Executing the Mustache Template
4.3.执行 “小胡子 “模板
The data provided to the template will be an instance of the Todo class which definition is:
提供给模板的数据将是Todo类的一个实例,其定义是。
public class Todo {
private String title;
private String text;
private boolean done;
private Date createdOn;
private Date completedOn;
// constructors, getters and setters
}
The compiled template can be executed to get HTML as shown below:
执行编译后的模板,可以得到如下所示的HTML。
Todo todo = new Todo("Todo 1", "Description");
StringWriter writer = new StringWriter();
m.execute(writer, todo).flush();
String html = writer.toString();
5. Mustache Sections and Iterations
5.小胡须的分段和迭代
Let’s now have a look at how to list the todos. For iterating over a list data, we make use of Mustache sections.
现在让我们来看看如何列出todos。为了对列表数据进行迭代,我们使用了Mustache部分。
A section is a block of code which is repeated one or more times depending on the value of the key in the current context.
一个部分是一个代码块,根据当前上下文中的键值,它被重复一次或多次。
It looks something like:
它看起来像。
{{#todo}}
<!-- Other code -->
{{/todo}}
A section begins with a pound (#) and ends with a slash (/), where each of the signs is followed by the key whose value is used as the basis for rendering the section.
一个部分以英镑(#)开始,以斜线(/)结束,其中每个符号后面都有一个键,其值被用作渲染该部分的基础。
Following are the scenarios that can occur depending on the value of the key:
以下是可能发生的情况,取决于键的值。
5.1. Section With Non-Empty List or Non-False Value
5.1.具有非空列表或非假值的部分
Let’s create a template todo-section.mustache which uses a section:
让我们创建一个模板todo-section.mustache,它使用一个section。
{{#todo}}
<h2>{{title}}</h2>
<small>Created on {{createdOn}}</small>
<p>{{text}}</p>
{{/todo}}
Let’s look at this template in 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<String, Object> context = new HashMap<>();
context.put("todo", todo);
String expected = "<h2>Todo 1</h2>";
assertThat(executeTemplate(m, todo)).contains(expected);
}
Let’s create another template todos.mustache for listing the todos:
让我们创建另一个模板todos.mustache来列出todos。
{{#todos}}
<h2>{{title}}</h2>
{{/todos}}
And create a listing of todos using it:
并使用它创建一个todos的清单。
@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. Section With Empty List or False or Null Value
5.2.带有空的List或False或Null值的部分
Let’s test the todo-section.mustache with a null value:
让我们用todo-section.mustache的值来测试null。
@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();
}
And likewise, test todos.mustache with an empty list:
同样地,用一个空列表测试todos.mustache。
@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. Inverted Sections
6.倒置的部分
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.
反转的部分是那些基于不存在的键或false或null值或空列表只渲染一次的部分。换句话说,这些是在一个部分没有呈现的时候呈现的。
These start with a caret (^) and end with a slash (/) as shown below:
如下图所示,这些代码以圆点(^)开始,以斜线(/)结束。
{{#todos}}
<h2>{{title}}</h2>
{{/todos}}
{{^todos}}
<p>No todos!</p>
{{/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<String, Object> context = new HashMap<>();
assertThat(executeTemplate(m, context).trim())
.isEqualTo("<p>No todos!</p>");
}
7. Lambdas
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.
mustache部分的键值可以是一个函数或一个lambda表达式。在这种情况下,完整的lambda表达式是通过传入该节内的文本作为lambda表达式的参数来调用的。
Let’s look at a template todos-lambda.mustache:
让我们看看一个模板todos-lambda.mustache。
{{#todos}}
<h2>{{title}}{{#handleDone}}{{doneSince}}{{/handleDone}}</h2>
{{/todos}}
The handleDone key resolves to a Java 8 lambda expression as shown below:
handleDone键解析为一个Java 8 lambda表达式,如下图所示。
public Function<Object, Object> handleDone() {
return (obj) -> done ?
String.format("<small>Done %s minutes ago<small>", obj) : "";
}
The HTML generated by executing the above template is:
执行上述模板所产生的HTML是。
<h2>Todo 1</h2>
<h2>Todo 2</h2>
<h2>Todo 3<small>Done 5 minutes ago<small></h2>
8. Conclusion
8.结论
In this introductory article, we looked at creating mustache templates with sections, inverted sections, and lambdas. And we used the Java API to compile and execute the templates by providing relevant data.
在这篇介绍性文章中,我们研究了用分段、反分段和lambdas创建mustache模板。并且我们使用了Java API,通过提供相关数据来编译和执行模板。
There are few more advanced features of Mustache that are worth exploring – such as:
Mustache还有一些更高级的功能值得探索–比如说。
- providing a callable as a value which results in a concurrent evaluation
- using DecoratedCollection to get first, last and index of collection elements
- invert API which gives the data given the text and the template
And, as always, the complete source code for this is available over on Github.
而且,像往常一样,其完整的源代码可在Github上获得,。