Thymeleaf 基本用法

本文深入讲解Thymeleaf模板引擎的基本用法,包括标准表达式、链接URL、引入js与css、条件判断、迭代循环等关键特性,以及如何在前后端分离的环境中高效运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Thymeleaf

  1. Thymeleaf是一个现代服务器端Java模板引擎,适用于Web和独立环境,能够处理HTML,XML,JavaScript,CSS甚至纯文本。
  2. Thymeleaf的主要目标是提供一种优雅且高度可维护的模板创建方式。为实现这一目标,它以自然模板的概念为基础,将其逻辑注入模板文件,其方式不会影响模板被用作设计原型。这改善了设计沟通,缩小了设计和开发团队之间的差距。
  3. Thymeleaf也从一开始就设计了Web标准 - 特别是HTML5 - 允许您创建完全验证的模板,如果您需要的话。
  4. 前后端分离,独立于服务器。

引用命名空间

<html xmlns:th="http://www.thymeleaf.org">

在html中引入此命名空间,可避免编辑器出现html验证错误,虽然加不加命名空间对Thymeleaf的功能没有任何影响。

标准表达式

· 简单表达式 (simple expressions)

  ${...}  变量表达式

  *{...}  选择变量表达式

  #{...}  消息表达式

  @{...}  链接url表达式

· 字面量

  'one text','another one!',...   文本

  0,34,3.0,12.3,... 数值

  true false 布尔类型

  null 空

    one,sometext,main 文本字符

· 文本操作

  +  字符串连接

  |The name is ${name}|  字符串连接

· 算术运算

  + , - , * , / , %  二元运算符

  -  负号(一元运算符)

· 布尔操作

  and,or  二元操作符

  !,not 非(一元操作符)

· 关系操作符

  > , < , >= , <= (gt , lt , ge , le)

  == , != (eq, ne)

· 条件判断

(if) ? (then)      if-then

(if) ? (then) : (else)   if-then-else  

链接URL

URL是Web应用程序模板中的一等公民,而Thymeleaf标准方言具有特殊的语法,@语法:@{…}
不同类型的网址:
1.绝对网址: http://www.thymeleaf.org
2.相对URL,可以是:
页面相对: user/login.html
上下文相关:( /itemdetails?id=3服务器中的上下文名称将自动添加)
服务器相对:( ~/billing/processInvoice允许在同一服务器中的另一个上下文(=应用程序)中调用URL)。
协议相对URL: //code.jquery.com/jquery-2.0.3.min.js

引入js与css

使用thymeleaf,当未连接服务器时,使用的是本地的连接href="",当应用thymeleaf时,使用的是th:href="",th:href会直接将本地数据替换,实现前后端的分离。

 <link rel="stylesheet"  th:href="@{/static/css/bootstrap.min.css}" href="../static/css/bootstrap.min.css" />
<script src="../js/jquery-3.3.1.min.js" th:src="@{/js/jquery-3.3.1.min.js}"></script>

现在大多都是使用html5,有时th:src和th:href会报错,对h5不友好,因此可以使用data-th-href

 <link rel="stylesheet"  data-th-href="@{/static/css/bootstrap.min.css}"  />
 <script src="../js/jquery-3.3.1.min.js" data-th-src="@{/js/jquery-3.3.1.min.js}"></script>

在其他文件引入head部分

<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="header">
  <meta charset="UTF-8" />
  <title th:text="#{head.title}"></title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
 <link rel="stylesheet"  data-th-href="@{/static/css/bootstrap.min.css}"  />
 <script src="../js/jquery-3.3.1.min.js" data-th-src="@{/js/jquery-3.3.1.min.js}"></script>
</head>

在要引用的页面 引入
他就相当于jsp 中我们常用的<%@ include file="/WEB-INF/jsp/public/header.jspf"%>

<head th:include="theme/fragments::header" /> 

a标签

<!-- Will produce 'http://localhost:8080/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html" 
   th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>

<!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>

<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>

根据指定的服务器相对路径来写

<a href="product/list.html" th:href="@{/product/list}">Product List</a>

img标签

<img src="../../images/logo.png"   th:src="@{/images/logo.png}" th:title="#{logo}" th:alt="#{logo}" />

img标签一次设置多个值,等同于

<img src="../../images/logo.png"  th:attr="src=@{/images/logo.png},title=#{logo},alt=#{logo}" />

获取变量值

文本输出

1.固定文字内容

<p>The year is <span th:text="2018">2019</span>.</p>


<p>
  Now you are looking at a <span th:text="'working web application'">template file</span>.
</p>

2.连接服务器内容

<p>
hello
<span th:text="${name}">name</span>
</p>

3.文本拼接

<span th:text="|Welcome to our application, ${user.name}!|">

<span th:text="'Welcome to our application, ' + ${user.name} + '!'">

算术运算

算术运算:+,-,*,/和%

<div th:with="isEven=(${prodStat.count} % 2 == 0)">

<div th:with="isEven=${prodStat.count % 2 == 0}">

条件表达式

<tr th:class="${row.even}? 'even' : 'odd'">
  ...
</tr>


<tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'">
  ...
</tr>

条件判断

1.a标签只有在th:if的情况下显示

<a th:if="${myself=='yes'}" > </i> </a>

2.unless与if正好相反

 <a th:unless=${session.user != null} th:href="@{/login}" >Login</a>

迭代(for循环)

 <tr th:each="prod : ${prods}">
      <td th:text="${prod.name}">Onions</td>
      <td th:text="${prod.price}">2.41</td>
      <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
 </tr>

保持迭代的状态

使用时th:each,Thymeleaf提供了一种机制,可用于跟踪迭代的状态:状态变量。

状态变量在th:each属性中定义,包含以下数据:

当前迭代索引,从0开始。这是index属性。
当前迭代索引,从1开始。这是count属性。
迭代变量中元素的总量。这是size酒店。
每次迭代的iter变量。这是current酒店。
当前迭代是偶数还是奇数。这些是even/odd布尔属性。
当前迭代是否是第一个。这是first布尔属性。
当前迭代是否是最后一次。这是last布尔属性。

    <table>
        <tr>
            <th>NAME</th>
            <th>PRICE</th>
            <th>IN STOCK</th>
        </tr>
        <tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
            <td th:text="${prod.name}">Onions</td>
            <td th:text="${prod.price}">2.41</td>
            <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
        </tr>
    </table>

状态变量(iterStat在此示例中)在th:each属性中通过在iter变量本身之后写入其名称来定义,用逗号分隔。就像iter变量一样,status变量的范围也是由持有该th:each属性的标记定义的代码片段。

切换语句(switch)

<div th:switch="${user.role}">
  <p th:case="'admin'">User is an administrator</p>
  <p th:case="#{roles.manager}">User is a manager</p>
  <p th:case="*">User is some other thing</p>
</div>

模版布局

  <div th:fragment="copy">
      &copy; 2011 The Good Thymes Virtual Grocery
    </div>

在需要引入的页面

<div th:insert="~{footer :: copy}"></div>
<!-- 相当于 -->

<div th:insert="footer :: copy"></div>

th:insert和th:replace(和th:include)之间的区别

th:insert 是最简单的:它只是插入指定的片段作为其主机标签的主体。

th:replace实际上用指定的片段替换它的主机标签。

th:include类似于th:insert,但不是插入片段,它只插入此片段的内容。

 <div th:insert="footer :: copy"></div>

  <div th:replace="footer :: copy"></div>

  <div th:include="footer :: copy"></div>

导致的结果

 <div>
    <footer>
      &copy; 2011 The Good Thymes Virtual Grocery
    </footer>
  </div>

  <footer>
    &copy; 2011 The Good Thymes Virtual Grocery
  </footer>

  <div>
    &copy; 2011 The Good Thymes Virtual Grocery
  </div>

内联

表达式内联

<p>Hello, [[${session.user.name}]]!</p>

相当于

<p>Hello, <span th:text="${session.user.name}">Sebastian</span>!</p>

优点
当你静态打开它们时,内联表达式将逐字显示在你的HTML文件中,所以你可能无法将它们用作设计原型了!
浏览器显示的将会是

Hello, [[${session.user.name}]]!

在设计实用性方面非常清楚。

禁用内联

可以禁用此机制,因为实际上可能存在我们确实希望输出[[…]]或[(…)]序列而不将其内容作为表达式处理的情况。为此,我们将使用th:inline=“none”:

<p th:inline="none">A double array looks like this: [[1, 2, 3], [4, 5]]!</p>

文字内联

文本内联与我们刚刚看到的表达内联功能非常相似,但它实际上增加了更多功能。必须明确启用它th:inline=“text”。

JavaScript内联

JavaScript内联允许

<script th:inline="javascript">
    ...
    var username = [(${session.user.name})];
    ...
</script>

js附加代码:

/*[+
var msg = 'This is a working application';
+]*/

js移除代码:

/*[- */
var msg = 'This is a non-working template';
/* -]*/

CSS内联

<style th:inline="css">
  ...
</style>
<style th:inline="css">
    .[[${classname}]] {
      text-align: [[${align}]];
    }
</style>

表达式实用程序对象

dates : java.util.Date的功能方法类。
calendars : 类似#dates,面向java.util.Calendar
numbers : 格式化数字的功能方法类
strings : 字符串对象的功能类,contains,startWiths,prepending/appending等等。
objects: 对objects的功能类操作。
bools: 对布尔值求值的功能方法。
arrays:对数组的功能类方法。
lists: 对lists功能类方法
sets
maps

常用例子

${#dates.format(date, 'dd/MMM/yyyy HH:mm')}
${#dates.arrayFormat(datesArray, 'dd/MMM/yyyy HH:mm')}
${#dates.listFormat(datesList, 'dd/MMM/yyyy HH:mm')}
${#dates.setFormat(datesSet, 'dd/MMM/yyyy HH:mm')}



${#dates.day(date)}                    // also arrayDay(...), listDay(...), etc.
${#dates.month(date)}                  // also arrayMonth(...), listMonth(...), etc.
${#dates.monthName(date)}              // also arrayMonthName(...), listMonthName(...), etc.
${#dates.monthNameShort(date)}         // also arrayMonthNameShort(...), listMonthNameShort(...), etc.
${#dates.year(date)}                   // also arrayYear(...), listYear(...), etc.
${#dates.dayOfWeek(date)}              // also arrayDayOfWeek(...), listDayOfWeek(...), etc.
${#dates.dayOfWeekName(date)}          // also arrayDayOfWeekName(...), listDayOfWeekName(...), etc.
${#dates.dayOfWeekNameShort(date)}     // also arrayDayOfWeekNameShort(...), listDayOfWeekNameShort(...), etc.
${#dates.hour(date)}                   // also arrayHour(...), listHour(...), etc.
${#dates.minute(date)}                 // also arrayMinute(...), listMinute(...), etc.
${#dates.second(date)}                 // also arraySecond(...), listSecond(...), etc.
${#dates.millisecond(date)}            // also arrayMillisecond(...), listMillisecond(...), etc.


 <span th:text="${#calendars.format(today,'dd MMMM yyyy')}">13 May 2011</span>

常用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:删除包含标签和所有的孩子。2.body:不包含标记删除,但删除其所有的孩子。3.tag:包含标记的删除,但不删除它的孩子。4.all-but-first:删除所有包含标签的孩子,除了第一个。5.none:什么也不做。这个值是有用的动态评估。
th:attr设置标签属性,多个属性可以用逗号分隔比如<p th:attr="src=@{/image/aa.jpg},title=${title}">内容,这样如果${title}=’这个是title’ 则结果就是<p src="/image/aa.jpg" title="这个是title">内容</p>

总结

1.thymeleaf适用于与后端交互较多的应用。
2.前后端独立开发。
3.未连接服务器的时候,也能很好的展示页面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值