Mustache简介

1.概述

在本文中,我们将关注Mustache模板,并使用它的一个JavaAPI来生成动态HTML内容。Mustache是一个无逻辑的模板引擎,用于创建动态内容,如HTML、配置文件等。

2.介绍

简单地说,引擎被归类为无逻辑的,因为它没有支持if-else语句和for循环的构造。Mustache模板由 {{}} 包围的标签名称组成(类似于胡子,因此得名)。

3.Maven依赖

模板的编译和执行可由多种语言支持,包括客户端和服务器端。为了能够处理Java中的模板,我们使用了它的Java库,该库可以作为Maven依赖项添加。 Java 8+:

xml 复制代码
<dependency>
    <groupId>com.github.spullara.mustache.java</groupId>
    <artifactId>compiler</artifactId>
    <version>0.9.4</version>
</dependency>

Java 6/7:

xml 复制代码
<dependency>
    <groupId>com.github.spullara.mustache.java</groupId>
    <artifactId>compiler</artifactId>
    <version>0.8.18</version>
</dependency>

4.用法

让我们看看一个简单的场景,它展示了如何:

  1. 编写一个简单的模板;
  2. 使用Java API编译模板;
  3. 通过提供必要的数据来执行。

4.1一个简单的Mustache模板

我们将创建一个简单的模板来显示待办事项任务的详细信息:

html 复制代码
<h2>{{title}}</h2>
<small>Created on {{createdOn}}</small>
<p>{{text}}</p>

在上面的模板中,卷曲括号({{}})中的字段可以是:

  1. Java类的方法和属性;
  2. Map对象的key

4.2编译Mustache模板

我们可以编译如下所示的模板:

java 复制代码
MustacheFactory mf = new DefaultMustacheFactory();
Mustache m = mf.compile("todo.mustache");

MustacheFactory在类路径中搜索给定的模板。在我们的示例中,我们将todo.mustache放在src/main/resources下。

4.3执行Mustache模板

提供给模板的数据将是Todo类的一个实例,其定义为:

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

可以执行编译后的模板来获得HTML,如下所示:

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

Mustache Sections and Iterations

现在让我们看看如何列出待办事项,为了迭代列表数据,我们使用Mustache sections。section是一个代码块,根据当前上下文中键的值重复一次或多次。 它看起来像:

js 复制代码
{{#todo}}
<!-- Other code -->
{{/todo}}

节以(#)开始,以斜线(/)结束,其中这两个符号后面都跟着一个key,该键的value是渲染section的基础。 以下是根据key的值可能的情况:

5.1具有非空列表或非假值的Section

创建一个模板todo-section.mustache,它使用一个section:

js 复制代码
{{#todo}}
<h2>{{title}}</h2>
<small>Created on {{createdOn}}</small>
<p>{{text}}</p>
{{/todo}}

让我们看看这个模板的作用:

java 复制代码
@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);
}

让我们创建另一个模板todos.mustache来列出todos

js 复制代码
{{#todos}}
<h2>{{title}}</h2>
{{/todos}}

并使用它创建一个待办事项列表:

java 复制代码
@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列表为空或值为False或Null的Section

让我们用一个null值测试todo-section.mustache:

java 复制代码
@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();
}

同样,用一个空list测试todos.mustache:

java 复制代码
@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

倒置Sections是指基于不存在的key、或者key为false或null值或空列表时,仅渲染一次的部分。换言之,倒置Sections在未渲染Sections时进行渲染。 它们以插入符号(^)开头,以斜线(/)结束,如下所示:

js 复制代码
{{#todos}}
<h2>{{title}}</h2>
{{/todos}}
{{^todos}}
<p>No todos!</p>
{{/todos}}

以上模板在提供空list时:

java 复制代码
@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

mustache section的key的值可以是函数或lambda表达式。在这种情况下,通过将section中的文本作为参数传递给lambda表达式来调用完整的lambda表达式。

让我们来看一个模板todos-lambda.mustache:

js 复制代码
{{#todos}}
<h2>{{title}}{{#handleDone}}{{doneSince}}{{/handleDone}}</h2>
{{/todos}}

handleDone的key解析为Java 8 lambda表达式,如下所示:

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

通过执行上述模板生成的HTML是:

js 复制代码
<h2>Todo 1</h2>
<h2>Todo 2</h2>
<h2>Todo 3<small>Done 5 minutes ago<small></h2>

8.结论

在这篇介绍性文章中,我们研究了创建带有section、inverted section和Lambda的mustache模板。我们使用Java API通过提供相关数据来编译和执行模板。 Mustache的一些更高级的功能值得探索,例如:

  1. 提供一个callable作为value,从而产生并发评估;
  2. 使用DecoratedCollection获取集合元素的第一个、最后一个和索引;
  3. 反转API,在给定文本和模板的情况下提供数据。
相关推荐
工业3D_大熊12 分钟前
3D可视化引擎HOOPS Luminate场景图详解:形状的创建、销毁与管理
java·c++·3d·docker·c#·制造·数据可视化
szc176716 分钟前
docker 相关命令
java·docker·jenkins
程序媛-徐师姐25 分钟前
Java 基于SpringBoot+vue框架的老年医疗保健网站
java·vue.js·spring boot·老年医疗保健·老年 医疗保健
yngsqq26 分钟前
c#使用高版本8.0步骤
java·前端·c#
尘浮生36 分钟前
Java项目实战II基于微信小程序的校运会管理系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
小白不太白95040 分钟前
设计模式之 模板方法模式
java·设计模式·模板方法模式
Tech Synapse42 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
xoxo-Rachel1 小时前
(超级详细!!!)解决“com.mysql.jdbc.Driver is deprecated”警告:详解与优化
java·数据库·mysql
乌啼霜满天2491 小时前
JDBC编程---Java
java·开发语言·sql