thymeleaf 模板语言简介
参考网址: https://blog.csdn.net/mlin_123/article/details/51816533
1.1 Thymeleaf 在有网络和无网络的环境下皆可运行,而且完全不需启动WEB应用,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。
这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;
当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
1.2 Thymeleaf 开箱即用的特性。它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
1.3 Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
相比于其他的模板引擎,Thymeleaf最大的特点是通过HTML的标签属性渲染标签内容,以下是一个Thymeleaf模板例子: <!DOCTYPE html > <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Good Thymes Virtual Grocery</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" type="text/css" media="all" href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" /> </head> <body> <p th:text="#{home.welcome}">Welcome to our grocery store!</p> </body> </html>
这是一段标准的HTML代码,这也就意味着通过浏览器直接打开它是可以正确解析它的结构并看到页面的样子。相比于其他的模板引擎在指定的位置通过 ${} 等表达式进行渲染,Thymeleaf则是一种针对HTML/XML定制的模板语言(当然它可以被扩展),它通过标签中的th:text属性来填充该标签的一段内容。上例中, <p th:text="#home.welcome}" >Welcome to our grocery store!</p>
意味着<p>
标签中的内容会被表达式 #{home.welcome} 的值所替代,无论模板中它的内容是什么,之所以在模板中“多此一举“地填充它的内容,完全是为了它能够作为原型在浏览器中直接显示出来。
标准表达式语法
变量 Thymeleaf模板引擎在进行模板渲染时,还会附带一个Context存放进行模板渲染的变量,在模板中定义的表达式本质上就是从Context中获取对应的变量的值: <p>Today is: <span th:text="${today}">13 february 2011</span>.</p>假设today的值为2016年7月14日,那么渲染结果为:<p>Today is: 2016年7月14日.</p>。
可见Thymeleaf的基本变量和JSP一样,都使用${.}表示获取变量的值。
url 处理 URL在Web应用模板中占据着十分重要的地位,需要特别注意的是Thymeleaf对于URL的处理是通过语法@{…}来处理的。 Thymeleaf支持绝对路径URL: <a th:href="@{http://www.thymeleaf.org}">Thymeleaf</a> 同时也能够支持相对路径URL: 1. 当前页面相对路径URL——user/login.html,通常不推荐这样写。 2. Context相关URL——/static/css/style.css 另外,如果需要Thymeleaf对URL进行渲染,那么务必使用th:href,th:src等属性,下面是一个例子: <!-- 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>
下面两种url写法是比较推荐使用的, <!-- Will produce '/order/details?orderId=3' (plus rewriting) --> <a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
<!-- Will produce '/order/3/details' (plus rewriting) --> <a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a> 几点说明: 上例中URL最后的(orderId=${o.id})表示将括号内的内容作为URL参数处理,该语法避免使用字符串拼接,大大提高了可读性, @{...}表达式中可以通过{orderId}访问Context中的orderId变量,
@{/order}是Context相关的相对路径,在渲染时会自动添加上当前Web应用的Context名字,假设context名字为app,那么结果应该是/app/order
字符串替换 很多时候可能我们只需要对一大段文字中的某一处地方进行替换,可以通过字符串拼接操作完成:<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
一种更简洁的方式是:<span th:text="|Welcome to our application, ${user.name}!|">, 当然这种形式限制比较多,|…|中只能包含变量表达式${…},不能包含其他常量、条件表达式等。
运算符 在表达式中可以使用各类算术运算符,例如+, -, *, /, % th:with="isEven=(${prodStat.count} % 2 == 0)" 逻辑运算符>, <, <=,>=,==,!=都可以使用,
>, <, >=, <= (gt, lt, ge, le)
== , != ( eq , ne )
gt
:great than(大于)>
ge
:great equal(大于等于)>=
eq
:equal(等于)==
lt
:less than(小于)<
le
:less equal(小于等于)<=
ne
:not equal(不等于)!=
唯一需要注意的是使用<,>时需要用它的HTML转义符: th:if="${prodStat.count} gt 1" th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
循环
渲染列表数据是一种非常常见的场景,例如现在有n条记录需要渲染成一个表格<table>,该数据集合必须是可以遍历的,使用th:each标签: <body> <h1>Product list</h1> <table> <tr> <th>NAME</th> <th>PRICE</th> <th>IN STOCK</th> </tr> <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> </table> <p> <a href="../home.html" th:href="@{/}">Return to home</a> </p> </body> 可以看到,需要在被循环渲染的元素(这里是)中加入th:each标签,其中th:each="prod : ${prods}"意味着对集合变量prods进行遍历,循环变量是prod在循环体中可以通过表达式访问
条件求值 If/Unless Thymeleaf中使用th:if和th:unless属性进行条件判断,下面的例子中,<a>标签只有在th:if中条件成立时才显示:
<a th:href="@{/login}" th:if=${session.user != null}>Login</a> th:unless于th:if恰好相反,只有表达式中的条件不成立,才会显示其内容。 Switch Thymeleaf同样支持多路选择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> </div> 默认属性default可以用*表示: <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>
Utilities 为了模板更加易用,Thymeleaf还提供了一系列Utility对象(内置于Context中),可以通过#直接访问: - #dates - #calendars - #numbers - #strings - arrays - lists - sets - maps - … 下面用一段代码来举例一些常用的方法: #dates /* * Format date with the specified pattern * Also works with arrays, lists or sets */ ${#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')} /* * Create a date (java.util.Date) object for the current date and time */ ${#dates.createNow()} /* * Create a date (java.util.Date) object for the current date (time set to 00:00) */ ${#dates.createToday()} #strings /* * Check whether a String is empty (or null). Performs a trim() operation before check * Also works with arrays, lists or sets */ ${#strings.isEmpty(name)} ${#strings.arrayIsEmpty(nameArr)} ${#strings.listIsEmpty(nameList)} ${#strings.setIsEmpty(nameSet)} /* * Check whether a String starts or ends with a fragment * Also works with arrays, lists or sets */ ${#strings.startsWith(name,'Don')} // also array*, list* and set* ${#strings.endsWith(name,endingFragment)} // also array*, list* and set* /* * Compute length * Also works with arrays, lists or sets */ ${#strings.length(str)} /* * Null-safe comparison and concatenation */ ${#strings.equals(str)} ${#strings.equalsIgnoreCase(str)} ${#strings.concat(str)} ${#strings.concatReplaceNulls(str)} /* * Random */ ${#strings.randomAlphanumeric(count)}
综合实例 (参考网址: https://blog.csdn.net/pdw2009/article/details/44700897)
(thymeleaf手册参考网址:https://blog.csdn.net/zrk1000/article/details/72667478)
迭代 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 1</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Answer for exercise 1: iteration</h1> <h2>Product list</h2> <table> <thead> <tr> <th>Description</th> <th>Price</th> <th>Available from</th> </tr> </thead> <tbody th:remove="all-but-first"> <tr th:each="product:${productList}"> <td th:text="${product.description}">Red Chair</td> <td th:text="${'$' + #numbers.formatDecimal(product.price, 1, 2)}">$123</td> <td th:text="${#dates.format(product.availableFrom, 'yyyy-MM-dd')}">2014-12-01</td> </tr> <tr> <td>White table</td> <td>$200</td> <td>15-Jul-2013</td> </tr> <tr> <td>Reb table</td> <td>$200</td> <td>15-Jul-2013</td> </tr> <tr> <td>Blue table</td> <td>$200</td> <td>15-Jul-2013</td> </tr> </tbody> </table> </body> </html>
迭代统计<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 2</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Solution for exercise 2: iteration stats</h1> <h2>Product list</h2> <table> <thead> <tr> <th>Index</th> <th>Description</th> <th>Price</th> <th>Available from</th> </tr> </thead> <tbody th:remove="all-but-first">
<!--
index: 当前的索引,从0开始
count: 当前的索引,从1开始
size:总数
current:
even/odd:
first
last
-->
<tr th:each="product, productStat: ${productList}"> <td th:text="${productStat.count}">1</td> <!--注意这里和上面的差别--> <td th:text="${product.description}">Red chair</td> <td th:text="${'$' + #numbers.formatDecimal(product.price, 1, 2)}">$350</td> <td th:text="${#dates.format(product.availableFrom, 'dd-MMM-yyyy')}">28-Jun-2013</td> </tr> <tr> <td>2</td> <td>White table</td> <td>$200</td> <td>15-Jul-2013</td> </tr> <tr> <td>3</td> <td>Reb table</td> <td>$200</td> <td>15-Jul-2013</td> </tr> <tr> <td>4</td> <td>Blue table</td> <td>$200</td> <td>15-Jul-2013</td> </tr> </tbody> </table> </body> </html>
条件判断
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 3</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Answer for exercise 3: conditions</h1> <h2>Product list</h2> <table> <thead> <tr> <th>Description</th> <th>Price</th> <th>Available from</th> <th></th> </tr> </thead> <tbody> <tr th:each="product : ${productList}"> <td th:text="${product.description}">Red chair</td> <td th:text="${'$' + #numbers.formatDecimal(product.price, 1, 2)}">$350</td> <td th:text="${#dates.format(product.availableFrom, 'dd-MMM-yyyy')}">28-Jun-2013</td> <td> <span th:if="${product.price lt 100}" class="offer">Special offer!</span> </td> </tr> </tbody> </table> </body> </html>
更多条件判断
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 4</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Answer for exercise 4: more on conditions</h1> <h2>Customer list</h2> <table> <thead> <tr> <th>First name</th> <th>Last name</th> <th>Gender</th> <th>Payment method</th> <th>Balance</th> </tr> </thead> <tbody th:remove="all-but-first"> <tr th:each="customer : ${customerList}"> <td th:text="${customer.firstName}">Peter</td> <td th:text="${customer.lastName}">Jackson</td> <!-- Use th:switch for selecting content based on ${customer.gender}. As genre can be null if unknown, better use ${customer.gender?.name()} for obtaining its name. --> <td th:switch="${customer.gender?.name()}"> <img th:case="'MALE'" src="../../../images/male.png" th:src="@{/images/male.png}" alt="Male" /> <!-- Use "/images/male.png" image --> <img th:case="'FEMALE'" src="../../../images/female.png" th:src="@{/images/female.png}" alt="Female" /> <!-- Use "/images/female.png" image --> <span th:case="*">Unknown</span> </td> <td> <span th:text="${customer.paymentMethod.description}">Direct debit</span> <!-- Show next message only when paymentMethod is not CREDIT_CARD --> <span th:unless="${customer.paymentMethod.name() == 'CREDIT_CARD'}" class="warn"> Payment must be done in the next 4 days </span> </td> <!-- Add class="enhanced" when balance is greater than 10000 --> <td th:class="${customer.balance gt 10000} ? 'enhanced'" th:text="${customer.balance}">350</td> </tr> <tr> <td>Mary</td> <td>Johanson</td> <td><img src="../../../images/female.png" /></td> <td><span>Credit card</span></td> <td>5000</td> </tr> <tr> <td>Robert</td> <td>Allen</td> <td><img src="../../../images/male.png" /></td> <td> <span>Credit card</span> <span class="warn">Payment must be done in the next 4 days</span> </td> <td class="enhanced">50000</td> </tr> </tbody> </table> </body> </html>
Spring表达式语言
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 5</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Solution for exercise 5: Spring Expression language</h1> <h2>Arithmetic expressions</h2> <p class="label">Four multiplied by minus six multiplied by minus two module seven:</p> <p class="answer" th:text="${4 * -6 * -2 % 7}">123</p> <h2>Object navigation</h2> <p class="label">Description field of paymentMethod field of the third element of customerList bean:</p> <p class="answer" th:text="${customerList[2].paymentMethod.description}">Credit card</p> <h2>Object instantiation</h2> <p class="label">Current time milliseconds:</p> <p class="answer" th:text="${new java.util.Date().getTime()}">22-Jun-2013</p> <h2>T operator</h2> <p class="label">Random number:</p> <p class="answer" th:text="${T(java.lang.Math).random()}">123456</p> </body> </html>
超链接 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 6</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Answer for exercise 6: links</h1> <h2>Product actions</h2> <ul> <li><a href="#" th:href="@{/exercise11/product.html(action='view')}">View product</a></li> <li><a href="#" th:href="@{/exercise11/product.html(action='edit')}">Edit product</a></li> </ul> </body> </html>
表单 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 7</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Solution for exercise 7: forms</h1> <h2>Customer edition</h2> <form action="saveCustomer.html" th:action="@{/exercise12/saveCustomer.html}" th:object="${customer}" method="post"> <input type="hidden" th:field="*{id}" /> <label for="firstName">First name:</label> <input type="text" th:field="*{firstName}" value="John" /> <label for="lastName">Last name:</label> <input type="text" th:field="*{lastName}" value="Wayne" /> Genre: <div th:each="gender : ${genders}" class="radio"> <input type="radio" th:value="${gender}" th:field="*{gender}" /> <label th:for="${#ids.prev('gender')}" th:text="${gender.description}">Male</label> </div> <div th:remove="all" class="radio"> <input type="radio" /> <label>Female</label> </div> <label for="paymentMethod">Payment method:</label> <select th:field="*{paymentMethod}" th:remove="all-but-first"> <option th:each="paymentMethod : ${paymentMethods}" th:value="${paymentMethod}" th:text="${paymentMethod.description}">Credit card</option> <option>Another payment method</option> <option>Another payment method</option> </select> <label for="balance">Balance (dollars):</label> <input type="text" th:field="*{balance}" size="10" value="2500" /> <input type="submit" /> </form> </body> </html>
内联 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 8</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Solution for exercise 8: inlining</h1> <h2>Birthday email</h2> <form action="#" method="post"> <label for="body">Message body:</label> <textarea id="body" name="body" th:inline="text"> Dear [[${customerName}]], it is our sincere pleasure to congratulate your in your birthday: Happy birthday [[${customerName}]]!!! See you soon, [[${customerName}]]. Regards, The Thymeleaf team </textarea> <input type="submit" value="Send mail" /> </form> </body> </html>
转义和非转义文本 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 9</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Solution for exercise 9: escaped and unescaped text</h1> <div th:text="${html}"> Some escaped text </div> <div th:utext="${html}"> Some unescaped text </div> </body> </html>
国际化 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title th:text="#{tutorial.exercise10}">Thymeleaf tutorial: exercise 10</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1 th:text="#{tutorial.exercise4}">Thymeleaf tutorial - Solution for exercise 10: internationalization</h1> <h2 th:text="#{product.info}">Product information</h2> <dl> <dt th:text="#{product.name}">Product name</dt> <dd th:text="${product.description}">Red chair</dd> <dt th:text="#{product.price}">Product price</dt> <dd th:text="${#numbers.formatDecimal(product.price, 1, 2)}">350</dd> <dt th:text="#{product.available}">Product available from</dt> <dd th:text="${#dates.format(product.availableFrom, 'dd-MMM-yyyy')}">28-Jun-2013</dd> </dl> </body> </html>
此时html需要相应的配置文件。例如如下配置文件: en: tutorial.exercise4=Thymeleaf tutorial - exercise 10: internationalization product.info=Product information product.name=Product name product.price=Product price product.available=Product available from back=Back
fr tutorial.exercise4=Tutorial De Thymeleaf - exercice 10: l'internationalisation product.info=Information du produit product.name=Nom du produit product.price=Prix du produit product.available=Produit disponible depuis back=Revenir
字符串拼接 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 11</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Answer for exercise 11: string concatenation</h1> <h2>Product information</h2> <dl> <dt>Product price</dt> <dd th:text="${'$'+product.price}">235</dd> </dl> </body> </html>
简单数据转换(数字,日期) <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 12</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Answer for exercise 12: bean values</h1> <h2>Product information</h2> <dl> <dt>Product name</dt> <dd th:text="${product.description}">red Chair</dd> <dt>Product price</dt> <dd th:text="${#numbers.formatDecimal(product.price, 1, 2)}">180</dd> <dt>Product available from</dt> <dd th:text="${#dates.format(product.availableFrom, 'yyyy-MM-dd')}">2014-12-01</dd> </dl> </body> </html>
bean值替换 <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf tutorial: exercise 13</title> <link rel="stylesheet" href="../../../css/main-static.css" th:href="@{/css/main.css}" /> <meta charset="utf-8" /> </head> <body> <h1>Thymeleaf tutorial - Answer for exercise 13: bean values</h1> <h2>Product information</h2> <dl> <dt>Product name</dt> <dd th:text="${product.description}">Red Chair</dd> <dt>Product price</dt> <dd th:text="${product.price}">350</dd> <dt>Product available from</dt> <dd th:text="${product.availableFrom}">2014-12-01</dd> </dl> </body> </html>
努力做一个伪程序员, 不管道路有多么的艰苦......
posted on 2018-04-04 11:08 努力做一个伪程序员 阅读(2051) 评论(0) 编辑 收藏 举报