# thymeleaf-example
**Repository Path**: jonathanzyf/thymeleaf-example
## Basic Information
- **Project Name**: thymeleaf-example
- **Description**: Thymeleaf核心组件使用示例,包括模板解析器ClassLoaderTemplateResolver,模版引擎TemplateEngine,上下文Context。
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2020-09-21
- **Last Updated**: 2025-01-02
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Thymeleaf 示例工程
## 介绍
Thymeleaf核心组件使用示例,包括模板解析器ClassLoaderTemplateResolver,模版引擎TemplateEngine,上下文Context。
## 语法
### 表达式
```
表达式声明 ${ ... }
链式取值 user.hobbies[0], user['hobbies'], user.get('hobbies')
```
### TemplateMode.TEXT
1. 表达式
```
[(${user.name})]
其中:
[( ... )] 为Inlined代码边界
${ ... } 为表达式边界
user.name 为取值表达式
```
2. 循环
```
[# th:each="v,vStat : ${users}"] [(${vStat.index})] [(${v.name})] [/]
其中:
[# ... ] ... [/] 为代码块边界
th:each 为循环声明
v,vStat : ${users} 为foreach循环表达式
vStat 为迭代上限信息,包括index,count,size,current,first,last,even,odd这些属性
```
3. 分支
```
[# th:if="not ${vStat.last}"],[/]
其中:
[# ... ] ... [/] 为代码块边界
th:if 为分支声明
not ${vStat.last} 为条件表达式
```
4. 函数
```
[(${#dates.format(user.birthday,'yyyy-MM-dd HH:mm:ss')})]
其中:
[( ... )] 为Inlined代码边界
${ ... } 为表达式边界
#dates.format( ... , 'yyyy-MM-dd HH:mm:ss') 为日期格式化函数
user.birthday 为取值表达式
```
### TemplateMode.HTML
1. 属性
```
其中:
th:value 为属性声明
${ ... } 为表达式边界
user.name + ' ' + user.id 为取值表达式
```
2. 循环
```
其中:
th:each 为循环声明
th:text 为为内容声明
th:class 为属性声明
v,vStat : ${users} 为foreach循环表达式
vStat 为迭代上限信息,包括index,count,size,current,first,last,even,odd这些属性
```
3. 分支
```
...
其中:
th:if 为分支声明
not ${#arrays.isEmpty(users)} 为条件表达式
```
4. 函数
```
其中:
th:text 为内容声明
${ ... } 为表达式边界
#dates.format( ... , 'yyyy-MM-dd HH:mm:ss') 为日期格式化函数
user.birthday 为取值表达式
```
### 内置函数
|名称|功能|实现类|示例|
|---|----|----|----|
|#dates|日期函数|org.thymeleaf.expression.Dates|#dates.format(v, 'yyyy-MM-dd HH:mm:ss')|
|#temporals|日期函数JDK8|org.thymeleaf.expression.Temporals|#temporals.format(v, 'yyyy-MM-dd HH:mm:ss')|
|#numbers|数值函数|org.thymeleaf.expression.Numbers|#numbers.formatDecimal(money, 0, 2)}|
|#strings|字符串函数|org.thymeleaf.expression.Strings|#strings.startsWith(s, '__')|
|#objects|对象函数|org.thymeleaf.expression.Objects|#objects.nullSafe(obj, '默认值')|
|#bools|布尔函数|org.thymeleaf.expression.Bools|#bools.listIsTrue(list)|
|#arrays|数组函数|org.thymeleaf.expression.Arrays|#arrays.isEmpty(arr)|
|#lists|列表函数|org.thymeleaf.expression.Lists|#lists.size(list)|
|#sets|Set函数|org.thymeleaf.expression.Sets|#sets.contains(set, 'item')|
|#maps|Map函数|org.thymeleaf.expression.Maps|#maps.containsKey(map, 'key')|
|#aggregates|聚集函数|org.thymeleaf.expression.Aggregates|#aggregates.sum(list)|
|#messages|消息函数|org.thymeleaf.expression.Messages|#messages.msg(msg, p1, p2)|
|#uris|URI函数|org.thymeleaf.expression.Uris|#uris.escapePath(path)|
|#ids|ID函数|org.thymeleaf.expression.Ids|#ids.seq('sms')|
### 基本对象
|名称|对象类型|适用范围|示例|
|---|---|---|---|
|#ctx|org.thymeleaf.context.Context||#ctx.getVariable('name')|
|#vars|等价于#ctx|||
|#locale|java.util.Locale||#locale.country 或 #locale.getCountry()|
|#httpServletRequest|HttpServletRequest|WebEngineContext||
|#httpSession|HttpSession|WebEngineContext||
## 使用
1. 引入JAR
```xml
org.thymeleaf
thymeleaf
3.0.11.RELEASE
```
2. 渲染方法
```java
private static String render(TemplateMode mode, String resources, String templateId, String key, Object data, String targetFile) throws IOException {
// 模板解析器
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
//模板所在目录,相对于当前classloader的classpath。
resolver.setPrefix(resources);
// 模板文件后缀
if (mode == TemplateMode.HTML) {
resolver.setSuffix(".html");
} else {
resolver.setSuffix(".tpl");
}
// 设置模式
resolver.setTemplateMode(mode);
// 模板引擎
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(resolver);
// 构造上下文
Context context = new Context();
context.setVariable(key, data);
// 渲染模版,输出到文件流
if (!StringUtils.isEmpty(targetFile)) {
try (FileWriter writer = new FileWriter(targetFile)) {
templateEngine.process(templateId, context, writer);
}
}
// 渲染模板,直接输出内容
String result = templateEngine.process(templateId, context);
return result;
}
```
3. 渲染测试
```java
public static void main(String[] args) throws IOException {
Map data = new HashMap<>();
data.put("id", 1001L);
data.put("name", "张三");
data.put("url", "http://www.bing.com");
data.put("createTime", new Date());
data.put("hobbies", new String[]{"Basketball", "Football", "Pingpang"});
System.out.println(data);
String json = render(TemplateMode.TEXT, "templates/json/", "json-he", "obj", data, "test.json");
System.out.println(json);
String html = render(TemplateMode.HTML, "templates/html/", "user", "obj", data, null);
System.out.println(html);
}
```
4. 配置Text模版
```json
{
"id":"[(${obj.get('id')})]",
"name":"[(${obj.get('name')})]",
"avatar":"[(${obj['url']})]",
"birthday": "[(${#dates.format(obj.get('createTime'),'yyyy-MM-dd HH:mm:ss')})]",
"hobbies": [
[# th:each="h:${obj.hobbies}"]"[(${h})]"[# th:if="not ${hStat.last}"],[/][/]
]
}
```
5. Text执行结果
```json
{
"id":"1001",
"name":"张三",
"avatar":"http://www.bing.com",
"birthday": "2020-09-17 17:35:12",
"hobbies": [
"Basketball","Football","Pingpang"
]
}
```
6. 配置HTML模版
```html
Test
```
7. HTML执行结果
```html
Test
```