Mustache 模板教程

本文学习Mustache 模板,并使用Java api动态生成HTML内容。Mustache是创建动态内的无逻辑模板引擎,如HTML,配置文件等。

1. 概述

Mustache属于无逻辑模板引擎,因为其不支持if-else和for语句,主要是有{{}}括起来的模板变量及包含模板数据的模型对象组成,因为双括号看起来像胡子,因此得名mustache

模板支持多种语言的客户端和服务器,当然也可以使用java库解析模板,需要引入相应依赖:
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>

读者也可以查找最新版本。

2. 实战使用

示例需求如下:

  1. 写个简单模板
  2. 使用Java Api编译模板
  3. 提供必要的数据生成动态内容

2.1. 简单模板

下面模板用于显示代办任务信息,命名为todo.mustache:

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

在{{}}中的模板变量可以是Java类的方法和属性,也是Map对象的key。

2.2. 编译模板

编译模板代码:

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

MustacheFactory 在类路径下搜索模板文件,我们的模板文件在src/main/resources路径下。

2.3. 执行模板

提供模板数据是Todo类的实例:

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

执行模板生成HTML内容的代码为:

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

3. Mustache的节(Section)和迭代

下面看如何列出所有代办事项,即迭代列表数据。这需要使用Mustache的节(Section),节是根据上下文中key的值决定重复一次或多次的代码块。
示例如下:

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

节以#号开头,/结尾,其中的变量会被解析用于渲染实际内容。下面介绍依据键的值可能遇到的场景。

3.1. 非空列表或非假值

首先定义 todo-section.mustache 模板:

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

来看看解析动作:

@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}}
<h2>{{title}}</h2>
{{/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>");
}

3.2. 空列表、假值或Null值

首先测试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();
}

同样使用空列表测试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();;
}

3.3. 条件表达式

else节(inverted section)用于当上下文变量值为false、null或空列表时渲染一次,类似于if...else...,但else部分只执行一次。
使用^符号开始,/结束:

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

使用空列表进行测试:

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

3.4. lambda表达式

模板中变量的值可以来自函数或lambda表达式。下面示例传入lambda表达式:

首先定义todos-lambda.mustache模板:

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

然后再Todo类中增加两个函数:

public Function<Object, Object> handleDone() {return (obj) -> done ? String.format("<small>Done %s minutes ago<small>", obj) : "";
}public long doneSince() {return done ? Duration.between(createdOn.toInstant(), completedOn.toInstant()).toMinutes() : 0;
}

最终生成内容为:

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

完整测试代码为:

import com.github.mustachejava.Mustache;
import org.junit.Test;import java.io.IOException;
import java.io.StringWriter;
import java.time.Instant;
import java.util.*;import static org.assertj.core.api.Assertions.assertThat;class MustacheTest {private String executeTemplate(Mustache m, Map<String, Object> context) throws IOException {StringWriter writer = new StringWriter();m.execute(writer, context).flush();return writer.toString();}@Testpublic void givenTodoList_whenGetHtmlUsingLamdba_thenHtml() throws IOException {Mustache m = MustacheUtil.getMustacheFactory().compile("todos-lambda.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"));todos.get(2).setDone(true);todos.get(2).setCompletedOn(Date.from(Instant.now().plusSeconds(300)));Map<String, Object> context = new HashMap<>();context.put("todos", todos);assertThat(executeTemplate(m, context).trim()).contains("Done 5 minutes ago");}
}

工具类MustacheUtil代码:

public class MustacheUtil {private MustacheUtil(){}private static final MustacheFactory MF = new DefaultMustacheFactory();public static MustacheFactory getMustacheFactory(){return MF;}
}

4. 总结

本文介绍了如何使用mustache 模板引擎,包括条件语法和lambda表达式,以及如何使用Java Api编译、渲染模板并生成目标内容。

Mustache 模板教程相关推荐

  1. mustache模板技术

    一.简介 Web 模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,通常是标准的 HTML 文档.当然不同的开发语言有不同模板引擎,如 Javascript 下的 Ho ...

  2. c++ 模板教程(c语言中文网) 自己运行实例

    注:本文的例子全部都是c语言中文网上的c++教程,自己只不过是运行了一遍而已.个别地方添加了点东西. 17.1模板函数教程 1.自己的第一个运行的程序(c语言中文网上源代码) // ConsoleAp ...

  3. 高质量项目管理-甘特图模板+教程(附下载包)/ PMP项目管理可用

    做项目管理的少不了用到甘特图,但项目流程那么多,每个都一一去做一个甘特图又需要耗费非常大的时间.所以这里给大家收集了一些甘特图模板+教程,供大家参考学习! 科普一下:甘特图(Gantt chart)又 ...

  4. Mustache 模板引擎

    Mustache 模板引擎 1.Mustache简介   mustache.js 是一个简单强大的 JavaScript 模板引擎.使用mustache前需要通过script标签引入它的js文件,然后 ...

  5. php网站套模板教程,PTCMS小说网站全新版源码+内附4套精美模板+教程

    源码介绍: 最新PTCMS小说精美多风格四套全新版源码+模板内附详细的安装教程,亲测完美搭建. 安装教程 安装宝塔面板一键安装环境 宝塔:www.bt.cn 必装环境:nginx(apache.iis ...

  6. PHP中如何用switch制作页面,php – 如何在Mustache模板中使用switch case?

    我在Core PHP中使用Mustache模板将PHP页面转换为模板.现在我想在模板中使用switch case,如: switch ($gift_card['FlagStatus']) { case ...

  7. 学习Vue的mustache语法-mustache模板引擎

    学习地址 : https://www.bilibili.com/video/BV1EV411h79m?vd_source=a81826692f4afea80764f4048dc1ae0a 代码地址 : ...

  8. Vue源码之mustache模板引擎(二) 手写实现mustache

    Vue源码之mustache模板引擎(二) 手写实现mustache mustache.js 个人练习结果仓库(持续更新):Vue源码解析 webpack配置 可以参考之前的笔记Webpack笔记 安 ...

  9. Vue源码之mustache模板引擎(一)

    Vue源码之mustache模板引擎(一) 个人练习结果仓库(持续更新):Vue源码解析 抽空把之前学的东西写成笔记. 学习视频链接:[尚硅谷]Vue源码解析之mustache模板引擎 模板引擎是什么 ...

最新文章

  1. ceph osd 由于“No space left on device” 异常down,通过扩容文件系统或者显式运行osd进程解决
  2. 部署ArcGIS JS API 离线包(Tomcat与IIS)
  3. linux下文件夹的创建、复制、剪切、重命名、清空和删除命令
  4. RSA大会播报 – 2014最佳安全博客提名
  5. [小程序]微信小程序获取input并发送网络请求
  6. sqlwarning mysql_mysql提示[Warning] Invalid (old?) table or database name问题的解决方法
  7. Springcloud 引导上下文
  8. 关于微信小程序下拉出现三个小点
  9. python 审批流_Odoo 基于企业微信实现的通用审批流功能的自助配置及使用说明 - Oejia 技术栈,企业方案分享、Odoo顾问...
  10. 关于springmvc配置validator的注意事项
  11. C++中的config设计
  12. CSDN网站系统升级公告
  13. 通过编写游戏程序的视角去编写字符驱动--设备树-百问imx6ull-pro
  14. 100天精通Andriod逆向——第2天:Android基础知识和jadx的使用
  15. Round 1—数据结构基本概念
  16. 2005-11-11
  17. 【C#】错误:不可访问,因为它具有一定的保护级别
  18. Keil5 点击Debug Setting 使软件奔溃的解决方法
  19. 柔性灌装自动化生产线实训系统
  20. 开发Chrome 插件赚钱的7个主要方式(Chrome Extension )

热门文章

  1. 程序员趣图:“菜鸟” VS “大神”
  2. NEFU CF 练习赛 45
  3. Factorization Meets the Neighborhood: a MultifacetedCollaborative Filtering Model 阅读笔记
  4. oracle 汉字正则表达式,oracle SQL篇-正则表达式
  5. tomcat 虚拟主机配置
  6. 基于自注意力机制的LSTM多变量负荷预测
  7. linux网络设置(有网卡别名介绍)
  8. 微信10亿日活场景下,微服务架构实践!15页PPT全解
  9. 常见测试函数图像及求解方法(一至四)
  10. channel.php id,channel.php