# Thymeleaf语法
## xmlns:th
```
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<!--/*@thymesVar id="name" type="java.lang.String"*/-->
<p th:text="'Hello!, ' + ${name} + '!'" >3333</p>
</body>
</html>
```
注意:`<html xmlns:th="http://www.thymeleaf.org">`用于解析模板里的`tf`标签
这样的话才可以在其他标签里面使用th:*这样的语法.这是下面语法的前提.
## 获取变量值
`<p th:text="'Hello!, ' + ${name} + '!'" >3333</p>`
可以看出获取变量值用$符号,对于javaBean的话使用变量名.属性名方式获取,这点和EL表达式一样.
另外$表达式只能写在th标签内部,不然不会生效,上面例子就是使用th:text标签的值替换p标签里面的值,至于p里面的原有的值只是为了给前端开发时做展示用的.这样的话很好的做到了前后端分离.
## 引入URL
Thymeleaf对于URL的处理是通过语法@{…}来处理的
```
<a th:href="@{http://blog.csdn.net/u012706811}">绝对路径</a>
<a th:href="@{/}">相对路径</a>
<a th:href="@{css/bootstrap.min.css}">Content路径,默认访问static下的css文件夹</a>
```
类似的标签有:th:href和th:src
## 字符串替换
很多时候可能我们只需要对一大段文字中的某一处地方进行替换,可以通过字符串拼接操作完成:
`<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)"`
逻辑运算符>, <, <=,>=,==,!=都可以使用,唯一需要注意的是使用<,>时需要用它的HTML转义符:
```
th:if="${prodStat.count} > 1"
th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
```
## 条件
### if/unless
Thymeleaf中使用th:if和th:unless属性进行条件判断,下面的例子中,标签只有在th:if中条件成立时才显示:
```
<a th:href="@{/login}" th:unless=${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>
```
## 循环
渲染列表数据是一种非常常见的场景,例如现在有n条记录需要渲染成一个表格
,该数据集合必须是可以遍历的,使用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在循环体中可以通过表达式访问。
th:each属性用于迭代循环,语法:th:each="obj,iterStat:${objList}"
迭代对象可以是java.util.List,java.util.Map,数组等;
iterStat称作状态变量,属性有:
```
index:当前迭代对象的index(从0开始计算)
count: 当前迭代对象的index(从1开始计算)
size:被迭代对象的大小
current:当前迭代变量
even/odd:布尔值,当前循环是否是偶数/奇数(从0开始计算)
first:布尔值,当前循环是否是第一个
last:布尔值,当前循环是否是最后一个
```
```
<ol>
<li>List循环:
<table border="1">
<tr>
<th>用户名</th>
<th>邮箱</th>
<th>管理员</th>
<th>状态变量:index</th>
<th>状态变量:count</th>
<th>状态变量:size</th>
<th>状态变量:current.userName</th>
<th>状态变量:even</th>
<th>状态变量:odd</th>
<th>状态变量:first</th>
<th>状态变量:last</th>
</tr>
<tr th:each="user,userStat : ${list}">
<td th:text="${user.userName}">Onions</td>
<td th:text="${user.email}">test@test.com.cn</td>
<td th:text="${user.isAdmin}">yes</td>
<th th:text="${userStat.index}">状态变量:index</th>
<th th:text="${userStat.count}">状态变量:count</th>
<th th:text="${userStat.size}">状态变量:size</th>
<th th:text="${userStat.current.userName}">状态变量:current</th>
<th th:text="${userStat.even}">状态变量:even****</th>
<th th:text="${userStat.odd}">状态变量:odd</th>
<th th:text="${userStat.first}">状态变量:first</th>
<th th:text="${userStat.last}">状态变量:last</th>
</tr>
</table>
</li>
<li>Map循环:
<div th:each="mapS:${map}">
<div th:text="${mapS}"></div>
</div>
</li>
<li>数组循环:
<div th:each="arrayS:${arrays}">
<div th:text="${arrayS}"></div>
</div>
</li>
</ol>
```
## Utilities工具
为了模板更加易用,Thymeleaf还提供了一系列Utility对象(内置于Context中),可以通过#直接访问:`
```
● #dates
● #calendars
● #numbers
● #strings
● arrays
● lists
● sets
● maps
● …
```
下面用一段代码来举例一些常用的方法:
### date
```
/*
* 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()}
string
/*
* 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)}
```
## 在文本中使用表达式
当然,我们同样可以在标签内赋值。
`<p>Hello, [[${session.user.name}]]!</p>`
效果和下面一样:
`<p>Hello, <span th:text="${session.user.name}">Sebastian</span>!</p>`
`[[…]]`之间的内容可以被赋值。为了使其生效,必须在此标签或者任何父标签上有th:inline属性。此属性有三种值(text , javascript and none)。text属性的用法:
`<p th:inline="text">Hello, [[${session.user.name}]]!</p>`
也可以在父标签上有此属性:
~~~
<body th:inline="text">
...
<p>Hello, [[${session.user.name}]]!</p>
...
</body>
~~~
## 在javaScript中使用表达式
### 给js变量赋值
表达式同样可以在javascript中使用。先用属性声明一下:`javascript ( th:inline=”javascript” )`,然后我们开始在js中声明变量:
~~~
<script th:inline="javascript">
/*<![CDATA[*/
...
var username = /*[[${session.user.name}]]*/ 'Sebastian';
...
/*]]>*/
</script>
~~~
`/*[[…]]*/`表达式的理解如下:
`/*…*/`中的内容在用浏览器打开静态 网页时,会被忽略。Sebastian会在浏览器中显示。Thymeleaf解析时,会解析`/*[[…]]*/`的内容,并把获得的值替换掉`/*[[…]]*/`里的内容。所以执行的结果如下:
~~~
<script th:inline="javascript">
/*<![CDATA[*/
...
var username = 'John Apricot';
...
/*]]>*/
</script>
~~~
你也可以不用注释:
~~~
<script th:inline="javascript">
/*<![CDATA[*/
...
var username = [[${session.user.name}]];
...
/*]]>*/
</script>
~~~
这会让它在静态显示时出现错误。
注意:引擎求值后注入是智能的,它可以智能赋值一下类型的数据。
~~~
Strings
Numbers
Booleans
Arrays
Collections
Maps
Beans (objects with getter and setter methods)
~~~
~~~
<script th:inline="javascript">
/*<![CDATA[*/
...
var user = /*[[${session.user}]]*/ null;
...
/*]]>*/
</script>
~~~
${session.user}会获取一个user对象。写入后如下:
~~~
<script th:inline="javascript">
/*<![CDATA[*/
...
var user = {'age':null,'firstName':'John','lastName':'Apricot',
'name':'John Apricot','nationality':'Antarctica'};
...
/*]]>*/
</script>
~~~
引擎同样允许增加和删除代码块,增加代码块:
~~~
var x = 23;
/*[+
var msg = 'This is a working application';
+]*/
var f = function() {
...
~~~
解析如下:
~~~
var x = 23;
var msg = 'This is a working application';
var f = function() {
...
~~~
删除代码块:
~~~
var x = 23;
/*[- */
var msg = 'This is a non-working template';
/* -]*/
var f = function(){
...
~~~
解析如下:
~~~
var x = 23;
var f = function(){
...
~~~