• Thymeleaf教程(10分钟入门)


    Thymeleaf教程(10分钟入门)

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。它与 JSP,Velocity,FreeMaker 等模板引擎类似,也可以轻易地与 Spring MVC 等 Web 框架集成。与其它模板引擎相比,Thymeleaf 最大的特点是,即使不启动 Web 应用,也可以直接在浏览器中打开并正确显示模板页面 。

    一. Thymeleaf 简介

    Thymeleaf 是新一代 Java 模板引擎,与 Velocity、FreeMarker 等传统 Java 模板引擎不同,Thymeleaf 支持 HTML 原型,其文件后缀为“.html”,因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 thymeleaf 模板的静态页面效果;当通过 Web 应用>程序访问时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示。
    Thymeleaf 通过在 html 标签中,增加额外属性来达到“模板+数据”的展示方式,示例代码如下。

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!--th:text 为 Thymeleaf 属性,用于在展示文本-->
    <h1 th:text="迎您来到Thymeleaf">欢迎您访问静态页面 HTML</h1>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    当直接使用浏览器打开时,浏览器展示结果如下。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9nSkOlHl-1657013815619)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\1.png)]

    当通过 Web 应用程序访问时,浏览器展示结果如下。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pmund1OJ-1657013815621)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\2.png)]

    Thymeleaf 的特点

    Thymeleaf 模板引擎具有以下特点:

    • 动静结合:Thymeleaf 既可以直接使用浏览器打开,查看页面的静态效果,也可以通过 Web 应用程序进行访问,查看动态页面效果。
    • 开箱即用:Thymeleaf 提供了 Spring 标准方言以及一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
    • 多方言支持:它提供了 Thymeleaf 标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式;必要时,开发人员也可以扩展和创建自定义的方言。
    • 与 SpringBoot 完美整合:SpringBoot 为 Thymeleaf 提供了的默认配置,并且还为 Thymeleaf 设置了视图解析器,因此 Thymeleaf 可以与 Spring Boot 完美整合。

    二. Thymeleaf 语法规则

    在使用 Thymeleaf 之前,首先需要导入thymeleaf依赖,然后在页面的 html 标签中声明名称空间,示例代码如下。

    <!-- thymeleaf依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    <html xmlns:th="http://www.thymeleaf.org">
        
    </html>
    
    • 1
    • 2
    • 3

    在 html 标签中声明此名称空间,可避免编辑器出现 html 验证错误,但这一步并非必须进行的,即使我们不声明该命名空间,也不影响 Thymeleaf 的使用。

    Thymeleaf 作为一种模板引擎,它拥有自己的语法规则。Thymeleaf 语法分为以下 2 类:

    • 标准表达式语法
    • th 属性

    2.1 基础语法

    2.1.1 变量表达式 ${}

    使用方法:直接使用 th:xx = “${}” 获取对象属性。例如:

    <form id="userForm">
        <input id="id" name="id" th:value="${user.id}"/>
        <input id="username" name="username" th:value="${user.username}"/>
        <input id="password" name="password" th:value="${user.password}"/>
    </form>
    
    <div th:text="hello"></div>
    
    <div th:text="${user.username}"></div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oZ7ta3MD-1657013815622)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\3.png)]

    2.1.2 选择变量表达式 *{}

    使用方法:首先通过th:object 获取对象,然后使用th:xx = "*{}"获取对象属性。
    这种简写风格极为清爽,推荐大家在实际项目中使用。 例如:

    <form id="userForm" th:object="${user}">
        <input id="id" name="id" th:value="*{id}"/>
        <input id="username" name="username" th:value="*{username}"/>
        <input id="password" name="password" th:value="*{password}"/>
    </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cUVQ0wMT-1657013815623)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\4.png)]

    2.1.3 链接表达式 @{}

    使用方法:通过链接表达式@{}直接拿到应用路径,然后拼接静态资源路径。例如:

    <script th:src="@{jquery/jquery-1.10.2.min.js}"></script>
    <link th:href="@{bootstrap/css/bootstrap.css}" rel="stylesheet" type="text/css">
    
    • 1
    • 2

    2.1.4 片段表达式 ~{}

    片段表达式是Thymeleaf的特色之一,细粒度可以达到标签级别,这是JSP无法做到的。
    片段表达式拥有三种语法:

    • ~{ viewName } 表示引入完整页面
    • ~{ viewName ::selector} 表示在指定页面寻找片段 其中selector可为片段名、jquery选择器等
    • ~{ ::selector} 表示在当前页寻找
      使用方法:首先通过th:fragment定制片段 ,然后通过th:replace 填写片段路径和片段名。例如:
    <!-- comm.html-->
    <head th:fragment="page">
        <scrpit th:src="@{jquery/jquery-1.10.2.min.js}"></scrpit>
    </head>
    <body>
        <h1>这是引入完整的页面</h1>
    </body>
    
    <!-- demo01.html -->
    <div th:replace="~{comm}"></div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nqnmgtq2-1657013815623)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\5.png)]

    <!-- comm.html-->
    <head th:fragment="page">
        <scrpit th:src="@{jquery/jquery-1.10.2.min.js}"></scrpit>
    </head>
    
    <!-- demo01.html -->
    <div th:replace="~{comm::page}"></div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XDAr5URE-1657013815624)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\6.png)]

    在实际使用中,我们往往使用更简洁的表达,去掉表达式外壳直接填写片段名。例如:

    <!-- demo01.html -->
    <div th:replace="comm::page"></div>
    
    • 1
    • 2

    值得注意的是,使用替换路径th:replace 开头请勿添加斜杠,避免部署运行的时候出现路径报错。(因为默认拼接的路径为spring.thymeleaf.prefix = classpath:/templates/

    2.1.5 消息表达式

    即通常的国际化属性:#{msg} 用于获取国际化语言翻译值。例如:

    <title th:text="#{user.title}"></title>
    
    • 1

    2.1.6 其它表达式

    在基础语法中,默认支持字符串连接、数学运算、布尔逻辑和三目运算等。例如:

    <input name="name" th:value="${'I am '+(user.name!=null ? user.name:'NoBody')}"/>
    
    • 1

    常用的 th 标签

    关键字功能介绍案例
    th:id替换id<input th:id="'xxx' + ${collect.id}"/>
    th:text文本替换<p th:text="${collect.description}">description</p>
    th:utext支持html的文本替换<p th:utext="${htmlcontent}">conten</p>
    th:object替换对象<div th:object="${session.user}">
    th:value属性赋值<input th:value="${user.name}"/>
    th:with变量赋值运算<div th:with="isEven=${prodStat.count}%2==0"></div>
    th:style设置样式th:style="'display:' + @{(${sitrue} ? 'none' : 'inline-block')} + ''"
    th:onclick点击事件th:onclick="'getCollect()'"
    th:each属性赋值tr th:each="user,userStat:${users}">
    th:if判断条件<a th:if="${userId == collect.userId}" >
    th:unless和th:if判断相反<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>
    th:href链接地址<a th:href="@{/login}" th:unless=${session.user != null}>Login</a> />
    th:switch多路选择 配合th:case 使用<div th:switch="${user.role}">
    th:caseth:switch的一个分支<p th:case="'admin'">User is an administrator</p>
    th:fragment布局标签,定义一个代码片段,方便其它地方引用<div th:fragment="alert">
    th:include布局标签,替换内容到引入的文件<head th:include="layout :: htmlhead" th:with="title='xx'"></head> />
    th:replace布局标签,替换整个标签到引入的文件<div th:replace="fragments/header :: title"></div>
    th:selectedselected选择框 选中th:selected="(${xxx.id} == ${configObj.dd})"
    th:src图片类地址引入<img class="img-responsive" alt="App Logo" th:src="@{/img/logo.png}" />
    th:inline定义js脚本可以使用变量<script type="text/javascript" th:inline="javascript">
    th:action表单提交的地址<form action="subscribe.html" th:action="@{/subscribe}">
    th:remove删除某个属性<tr th:remove="all"> 1.all:删除包含标签和所有的孩子。
    th:attr设置标签属性,多个属性可以用逗号分隔比如 th:attr="src=@{/image/aa.jpg},title=#{logo}",此标签不太优雅,一般用的比较少。

    还有非常多的标签,这里只列出最常用的几个,由于一个标签内可以包含多个th:x属性,其生效的优先级顺序为:
    include,each,if/unless/switch/case,with,attr/attrprepend/attrappend,value/href,src ,etc,text/utext,fragment,remove。

    三、内置对象

    3.1 七大内置对象

    • ${#ctx} 上下文对象,可用于获取其它内置对象。

    • ${#vars}: 上下文变量。

    • ${#locale}:上下文区域设置。

    • ${#request}: HttpServletRequest对象。

    • ${#response}: HttpServletResponse对象。

    • ${#session}: HttpSession对象。

    • ${#servletContext}: ServletContext对象。

    3.2 常用的工具类:

    • #strings:字符串工具类

    • #lists:List 工具类

    • #arrays:数组工具类

    • #sets:Set 工具类

    • #maps:常用Map方法。

    • #objects:一般对象类,通常用来判断非空

    • #bools:常用的布尔方法。

    • #execInfo:获取页面模板的处理信息。

    • #messages:在变量表达式中获取外部消息的方法,与使用#{…}语法获取的方法相同。

    • #uris:转义部分URL / URI的方法。

    • #conversions:用于执行已配置的转换服务的方法。

    • #dates:时间操作和时间格式化等。

    • #calendars:用于更复杂时间的格式化。

    • #numbers:格式化数字对象的方法。

    • #aggregates:在数组或集合上创建聚合的方法。

    • #ids:处理可能重复的id属性的方法。

    四、迭代循环

    想要遍历List集合很简单,配合th:each 即可快速完成迭代。例如遍历用户列表:

    <div th:each="user:${users}">
           id:<input id="id" name="id" th:value="${user.id}"/> <br>
           姓名:<input id="username" name="username" th:value="${user.username}"/> <br>
    </div>
    
    • 1
    • 2
    • 3
    • 4

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j5b118Sk-1657013815625)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\7.png)]

    在集合的迭代过程还可以获取状态变量,只需在变量后面指定状态变量名即可,状态变量可用于获取集合的下标/序号、总数、是否为单数/偶数行、是否为第一个/最后一个。例如:

    <table>
        <tr>
            <td>下标</td>
            <td>序号</td>
            <td>id</td>
            <td>姓名</td>
            <td>年龄</td>
        </tr>
    
        <tr th:each="user,item:${users}">
            <td th:text="${item.index}">index</td>
            <td th:text="${item.count}">count</td>
            <td th:text="${user.id}">id</td>
            <td th:text="${user.username}">姓名</td>
            <td th:text="${user.age}">年龄</td>
        </tr>
    </table>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6tUawEDY-1657013815625)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\8.png)]

    五、条件判断

    条件判断通常用于动态页面的初始化,例如:

    <div th:if="${users}">
        <div>哈哈哈,users存在</div>
    </div>
    
    • 1
    • 2
    • 3

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EGSIJnwE-1657013815626)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\9.png)]

    如果想取反则使用unless 例如:

    <div th:unless="${userList}">
        <div>不存在..</div>
    </div>
    
    • 1
    • 2
    • 3

    六、日期格式化

    使用默认的日期格式并不是我们预期的格式:Tue Jul 05 13:48:47 CST 2022

    <h1 th:text="${user.creatTime}"></h1>
    
    • 1

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gb5SgERN-1657013815626)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\10.png)]

    此时可以通过时间工具类#dates来对日期进行格式化:2022-70-05 13:50:23

    <h1 th:text="${#dates.format(user.createTime,'yyyy-MM-dd HH:mm:ss')}"></h1>
    
    • 1

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ntau8SmW-1657013815627)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\11.png)]

    七、内联写法

    • (1) 为什么要使用内联写法?
      答: 因为 JS 无法获取服务端返回的变量

    • (2) 如何使用内联表达式?
      答: 标准格式:[[${xx}]],可以读取服务端变量,也可以调用内置对象的方法。例如获取用户变量和应用路径:

    <script>
        var users = `[[${userList}]]`;
        console.log("users :" + users)
    </script>
    
    • 1
    • 2
    • 3
    • 4

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SEtCmMrL-1657013815627)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\12.png)]

    • (3) 标签引入的 JS 里面能使用内联表达式吗?

      答: 不能!内联表达式仅在页面生效,因为Thymeleaf只负责解析一级视图,不能识别外部标签 JS 里面的表达式。

    九、Demo案例

    创建 SpringBoot 项目,如图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fL7YKlhA-1657013815628)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\demo01.png)]

    引入相关依赖

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- web相关依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- thymeleaf依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- 热部署依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    然后在 application.yml 中配置

    spring:
      thymeleaf:
        prefix: classpath:/templates/
        suffix: .html
    
    • 1
    • 2
    • 3
    • 4

    编写 User 实体类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private Integer id;
        private String username;
        private String password;
        private String address;
        private Date createTime;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    编写 controller 层,返回用户信息

    @Controller
    public class UserController {
    
        @RequestMapping("/get")
        public String test01(Model model){
            ArrayList<User> userList = new ArrayList<>();
    
            userList.add(new User(1,"名字1","123456","成都",new Date()));
            userList.add(new User(2,"名字2","456789","grgk",new Date()));
            userList.add(new User(3,"名字3","789123","成都",new Date()));
            userList.add(new User(4,"名字4","987654","grgk",new Date()));
    
            model.addAttribute("userList",userList);
            return "user";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    编写前端 user.html 页面

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div th:each="user,userStat:${userList}">
            序号:<input type="text" th:value="${userStat.count}">
            账号:<input type="text" th:value="${user.username}">
            密码:<input type="text" th:value="${user.password}">
            时间:<input type="text" th:value="${user.createTime}">
            格式化后的时间:<input type="text" th:value="${#dates.format(user.createTime,'yyyy-MM-dd HH:mm:ss')}">
        </div>
    </body>
    
    <script>
        var users = `[[${userList}]]`;
        console.log("users :" + users)
    </script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    然后访问 http://localhost:8080/get 运行结果如图所示

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Iemweunh-1657013815628)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\demo02.png)]

    u s e r . u s e r n a m e " > 密 码 : < i n p u t t y p e = " t e x t " t h : v a l u e = " {user.username}"> 密码:<input type="text" th:value=" user.username"><inputtype="text"th:value="{user.password}">
    时间:
    格式化后的时间:

    ```

    然后访问 http://localhost:8080/get 运行结果如图所示

    [外链图片转存中…(img-Iemweunh-1657013815628)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LpodE6Qw-1657013815628)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\demo22.png)]

  • 相关阅读:
    损失函数(Loss Function)与代价函数(Cost Function)、目标函数(Objective Function)区别
    Ubuntu系统下把视频转换成gif图片
    某校帮签到小程序m 加密参数解析
    RabbitMQ 知识点解读
    KT148A语音芯片SOP外挂功放芯片8002D的说明_V1
    Python 爬虫 NO.4 HTTP 响应状态码
    不太会讲爱,其实已经偷偷幸福很久啦----我们的故事
    Layui快速入门之第五节 导航
    读懂跨链技术未来可能性:存在哪些机遇及进展?
    Hive如何使用Java自定义函数
  • 原文地址:https://blog.csdn.net/Sunblogy/article/details/125624677