# 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
    ```