thymeleaf常用语法

一、概述

thymeleaf是服务器端模板引擎,能够处理HTML、XML、JavaScript、CSS、文本等。thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。

thymeleaf官网
thymeleaf官网使用手册

二、thymeleaf工程配置

1.spring配置

<dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-thymeleaf</artifactId> 
</dependency> 

2.thymeleaf使用详细配置

#配置到properties文件中 
#thymeleaf start 
#spring.thymeleaf.mode的默认值是HTML5,其实是一个很严格的检查,改为LEGACYHTML5可以得到一个可能更友好亲切的格式要求 
spring.thymeleaf.mode=LEGACYHTML5 
spring.thymeleaf.encoding=UTF-8 
spring.thymeleaf.content-type=text/html 
#开发时关闭缓存,不然没法看到实时页面 
spring.thymeleaf.cache=false 
#thymeleaf end 

注:LEGACYHTML5需要搭配一个额外的库NekoHTML才可用,需在pom.xml文件中添加该依赖,如下:
<dependency> <groupId>net.sourceforge.nekohtml</groupId> <artifactId>nekohtml</artifactId> <version>1.9.22</version> </dependency>

三、thymeleaf 示例

@Controller 
public class HelloWorldController { 
   private static final Logger log = LoggerFactory.getLogger(HelloController.class); 

   @GetMapping(value = "/helloworld") 
   public String hello(Model model) { 
       String name = "thymeleaf"; 
       model.addAttribute("name", name); 
       return "helloworld"; 
   } 
} 

helloworld.html

<!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="${name} + ',HelloWorld,Welcome!'">静态页面文本显示</p> 
</body> 
</html> 

## 四、基础语法
1.使html支持thymeleaf

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

2.获取变量值${}

 <p th:text="${name} + ',HelloWorld,Welcome!'">静态页面文本显示</p> 

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

<div th:object="${session.user}"> 
    <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p> 
    <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p> 
    <p>Nationality: <span th:text={nationality}">Saturn</span>.</p> 
</div> 
<!--等价于--> 
<div> 
    <p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p> 
    <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p> 
    <p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p> 
</div> 

<p> 里面的原有的值是为给前端开发时做展示用的,这样在无网络的情况下也能运行。即完全可以前端先写出页面,模拟数据展现效果,后端人员再拿此模板修改即可。

4.链接表达式: @{…}
用来配合link、src、href使用的语法,类似的标签有:th:href和th:src

<!-- http://localhost:8080/demo/profile?userId=xxx--> 
<a href="userProfile.html" th:href="@{http://localhost:8080/demo/profile(userId=${user.id})}">view</a> 
<!--/login?username=xxx --> 
<a href="userProfile.html" th:href="@{/demo/profile(userId=${user.id})}">view</a> 

5.消息表达式#{}
通常与th:text属性一起使用,指明声明了th:text标签的文本是#{}中的key多对应的value,而标签内的文本将不显示

<!-- 
/WEB-INF/templates/demo.properties 
home.welcome = this message is from demo.properties 
--> 
<!-- /WEB-INF/templates/demo.html --> 
<p th:text = "#{demo.welcome}">welcome<p> 

6.工具对象表达式 #maps
常用于日期、集合、数组对象的访问。这些工具对象就是java对象,可以访问对应java对象的方法来进行各种操作。

<div th:if="${#maps.size(studentVO.students[__${rowStat.index}__].score)!=0}"> 
<label>${score.key}:</label><input type="text" th:value="${score.value}"> 
</div> 

其他工具对象表达式还有:#dates、#calendars、#numbers、#strings、#objects、#bools、#arrays、#lists、#sets

工具对象参考官网手册

/* 
 * 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()} 


/*
 * Format calendar with the standard locale format
 * Also works with arrays, lists or sets
 */
${#calendars.format(cal)}
${#calendars.arrayFormat(calArray)}
${#calendars.listFormat(calList)}
${#calendars.setFormat(calSet)}

/*
 * Format calendar with the ISO8601 format
 * Also works with arrays, lists or sets
 */
${#calendars.formatISO(cal)}
${#calendars.arrayFormatISO(calArray)}
${#calendars.listFormatISO(calList)}
${#calendars.setFormatISO(calSet)}

/*
 * Format calendar with the specified pattern
 * Also works with arrays, lists or sets
 */
${#calendars.format(cal, 'dd/MMM/yyyy HH:mm')}
${#calendars.arrayFormat(calArray, 'dd/MMM/yyyy HH:mm')}
${#calendars.listFormat(calList, 'dd/MMM/yyyy HH:mm')}
${#calendars.setFormat(calSet, 'dd/MMM/yyyy HH:mm')}

/*
 * Obtain calendar properties
 * Also works with arrays, lists or sets
 */
${#calendars.day(date)}                // also arrayDay(...), listDay(...), etc.
${#calendars.month(date)}              // also arrayMonth(...), listMonth(...), etc.
${#calendars.monthName(date)}          // also arrayMonthName(...), listMonthName(...), etc.
${#calendars.monthNameShort(date)}     // also arrayMonthNameShort(...), listMonthNameShort(...), etc.
${#calendars.year(date)}               // also arrayYear(...), listYear(...), etc.
${#calendars.dayOfWeek(date)}          // also arrayDayOfWeek(...), listDayOfWeek(...), etc.
${#calendars.dayOfWeekName(date)}      // also arrayDayOfWeekName(...), listDayOfWeekName(...), etc.
${#calendars.dayOfWeekNameShort(date)} // also arrayDayOfWeekNameShort(...), listDayOfWeekNameShort(...), etc.
${#calendars.hour(date)}               // also arrayHour(...), listHour(...), etc.
${#calendars.minute(date)}             // also arrayMinute(...), listMinute(...), etc.
${#calendars.second(date)}             // also arraySecond(...), listSecond(...), etc.
${#calendars.millisecond(date)}        // also arrayMillisecond(...), listMillisecond(...), etc.

/*
 * Create calendar (java.util.Calendar) objects from its components
 */
${#calendars.create(year,month,day)}
${#calendars.create(year,month,day,hour,minute)}
${#calendars.create(year,month,day,hour,minute,second)}
${#calendars.create(year,month,day,hour,minute,second,millisecond)}

${#calendars.createForTimeZone(year,month,day,timeZone)}
${#calendars.createForTimeZone(year,month,day,hour,minute,timeZone)}
${#calendars.createForTimeZone(year,month,day,hour,minute,second,timeZone)}
${#calendars.createForTimeZone(year,month,day,hour,minute,second,millisecond,timeZone)}

/*
 * Create a calendar (java.util.Calendar) object for the current date and time
 */
${#calendars.createNow()}

${#calendars.createNowForTimeZone()}

/*
 * Create a calendar (java.util.Calendar) object for the current date (time set to 00:00)
 */
${#calendars.createToday()}

${#calendars.createTodayForTimeZone()}

/*
 * ==========================
 * Formatting integer numbers
 * ==========================
 */

/* 
 * Set minimum integer digits.
 * Also works with arrays, lists or sets
 */
${#numbers.formatInteger(num,3)}
${#numbers.arrayFormatInteger(numArray,3)}
${#numbers.listFormatInteger(numList,3)}
${#numbers.setFormatInteger(numSet,3)}


/* 
 * Set minimum integer digits and thousands separator: 
 * 'POINT', 'COMMA', 'WHITESPACE', 'NONE' or 'DEFAULT' (by locale).
 * Also works with arrays, lists or sets
 */
${#numbers.formatInteger(num,3,'POINT')}
${#numbers.arrayFormatInteger(numArray,3,'POINT')}
${#numbers.listFormatInteger(numList,3,'POINT')}
${#numbers.setFormatInteger(numSet,3,'POINT')}


/*
 * ==========================
 * Formatting decimal numbers
 * ==========================
 */

/*
 * Set minimum integer digits and (exact) decimal digits.
 * Also works with arrays, lists or sets
 */
${#numbers.formatDecimal(num,3,2)}
${#numbers.arrayFormatDecimal(numArray,3,2)}
${#numbers.listFormatDecimal(numList,3,2)}
${#numbers.setFormatDecimal(numSet,3,2)}

/*
 * Set minimum integer digits and (exact) decimal digits, and also decimal separator.
 * Also works with arrays, lists or sets
 */
${#numbers.formatDecimal(num,3,2,'COMMA')}
${#numbers.arrayFormatDecimal(numArray,3,2,'COMMA')}
${#numbers.listFormatDecimal(numList,3,2,'COMMA')}
${#numbers.setFormatDecimal(numSet,3,2,'COMMA')}

/*
 * Set minimum integer digits and (exact) decimal digits, and also thousands and 
 * decimal separator.
 * Also works with arrays, lists or sets
 */
${#numbers.formatDecimal(num,3,'POINT',2,'COMMA')}
${#numbers.arrayFormatDecimal(numArray,3,'POINT',2,'COMMA')}
${#numbers.listFormatDecimal(numList,3,'POINT',2,'COMMA')}
${#numbers.setFormatDecimal(numSet,3,'POINT',2,'COMMA')}



/*
 * ==========================
 * Utility methods
 * ==========================
 */

/*
 * Create a sequence (array) of integer numbers going
 * from x to y
 */
${#numbers.sequence(from,to)}
${#numbers.sequence(from,to,step)}

/*
 * Converts to array, trying to infer array component class.
 * Note that if resulting array is empty, or if the elements
 * of the target object are not all of the same class,
 * this method will return Object[].
 */
${#arrays.toArray(object)}

/*
 * Convert to arrays of the specified component class.
 */
${#arrays.toStringArray(object)}
${#arrays.toIntegerArray(object)}
${#arrays.toLongArray(object)}
${#arrays.toDoubleArray(object)}
${#arrays.toFloatArray(object)}
${#arrays.toBooleanArray(object)}

/*
 * Compute length
 */
${#arrays.length(array)}

/*
 * Check whether array is empty
 */
${#arrays.isEmpty(array)}

/*
 * Check if element or elements are contained in array
 */
${#arrays.contains(array, element)}
${#arrays.containsAll(array, elements)}

/*
 * Converts to list
 */
${#lists.toList(object)}

/*
 * Compute size
 */
${#lists.size(list)}

/*
 * Check whether list is empty
 */
${#lists.isEmpty(list)}

/*
 * Check if element or elements are contained in list
 */
${#lists.contains(list, element)}
${#lists.containsAll(list, elements)}

/*
 * Sort a copy of the given list. The members of the list must implement
 * comparable or you must define a comparator.
 */
${#lists.sort(list)}
${#lists.sort(list, comparator)}

/*
 * Converts to set
 */
${#sets.toSet(object)}

/*
 * Compute size
 */
${#sets.size(set)}

/*
 * Check whether set is empty
 */
${#sets.isEmpty(set)}

/*
 * Check if element or elements are contained in set
 */
${#sets.contains(set, element)}
${#sets.containsAll(set, elements)}

/*
 * Compute size
 */
${#maps.size(map)}

/*
 * Check whether map is empty
 */
${#maps.isEmpty(map)}

/*
 * Check if key/s or value/s are contained in maps
 */
${#maps.containsKey(map, key)}
${#maps.containsAllKeys(map, keys)}
${#maps.containsValue(map, value)}
${#maps.containsAllValues(map, value)}

/* 
 * 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)} 

7.文本替换

<span th:text="'Welcome to our application, ' + ${user.name} + '!'"> 
<!-- 等同于下面的表达式;下面的表达式只能包含表达式变量,而不能有条件判断等!--> 
<span th:text="|Welcome to our application, ${user.name}!|"> 

8.运算符

  • 数学运算
    二元操作:+, - , * , / , %
    一元操作: - (负)
  • 逻辑运算
    一元 : and or
    二元 : !,not
  • 比较运算(为避免转义尴尬,可以使用括号中的英文进行比较运算!)
    比较:> , < , >= , <= ( gt , lt , ge , le )
    等于:== , != ( eq , ne )
  • 条件运算
    If-then: (if) ? (then)
    If-then-else: (if) ? (then) : (else)
    (value) ?: (defaultvalue)

9.条件
th:if、th:unless(th:unless于th:if恰好相反,只有表达式中的条件不成立,才会显示其内容)、th:switch

<a th:href="@{/login}" th:if=${session.user == null}>Login</a> 
<!-- 等同于下面的表达式 --> 
<a th:href="@{/login}" th:unless=${session.user != null}>Login</a> 
<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> 

10.循环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(从0开始计算)</th> 
        <th th:text="${userStat.count}"> 当前迭代对象的index(从1开始计算)</th> 
        <th th:text="${userStat.size}">被迭代对象的大小</th> 
        <th th:text="${userStat.current.userName}">当前迭代变量</th> 
        <th th:text="${userStat.even}">状态变量:even****</th> 
        <th th:text="${userStat.odd}">布尔值,当前循环是否是偶数/奇数(从0开始计算)</th> 
        <th th:text="${userStat.first}">布尔值,当前循环是否是第一个</th> 
        <th th:text="${userStat.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> 

五、常用标签

  • th:action
    定义后台控制器路径,类似标签的action属性
<form id="login-form" th:action="@{/login}">...</form> 
  • th:each
    对象遍历,功能类似jstl中的<c:forEach>标签
public class StudentVO{ 
        private List<Student> students; 
} 
public class Student implements Serializable{ 
        private String firstName; 
        private String lastName; 
} 

@RequestMapping(value = "/addStudent", method = RequestMethod.POST) 
public String addStudent(@ModelAttribute(value = "studentVO") 
StudentVO studentVO,ModelMap model) {...} 
<form id="login-form" th:action="@{/addStudent}" th:object="${studentVO}" method="POST"> 
<div class="student" th:each="stus,rowStat:${studentVO.students}"> 
<input type="text" class="firstName" value="" th:field="*{students[__${rowStat.index}__].firstName}"></input> 
<input type="text" class="lastName" value="" th:field="*{students[__${rowStat.index}__].lastName}"></input> 
</div> 
</form> 
  • th:field
    常用于表单字段绑定。通常与th:object一起使用。 属性绑定、集合绑定
public class LoginBean implements Serializable{... 
    private String username; 
    private List<User> user; 
} 
public class User implements Serializable{... 
    private String username;; 
} 

@RequestMapping(value = "/login", method = RequestMethod.POST) 
public String login(@ModelAttribute(value = "loginBean") LoginBean loginBean,ModelMap model) {..} 
<form id="login-form" th:action="@{/login}" th:object="${loginBean}">... 
    <input type="text" value="" th:field="*{username}"></input> 
    <input type="text" value="" th:field="*{user[0].username}"></input> 
</form> 
  • th:href
    定义超链接,类似标签的href 属性。value形式为@{/logout}
<a th:href="@{/logout}" class="signOut"></a> 
  • th:id
    div id声明,类似html标签中的id属性
<div class="student" th:id = "student+(${rowStat.index}+1)"></div> 
  • th:if
    条件判断
<div th:if="${rowStat.index} == 0">... 该div显示 ...</div> 
  • th:include
    见th:fragment,如下

  • th:replace
    见th:fragment,如下

  • th:fragment
    声明定义该属性的div为模板片段,常用与头文件、页尾文件的引入。常与th:include,th:replace一起使用

<!-- 声明模板片段/WEBINF/templates/footer. html --> 
<div th: fragment=" copy" > 
© 2011 The Good Thymes Virtual Grocery 
</div> 

<!-- 引入模板片段 --> 
<div th: include=" /templates/footer : : copy" ></div> 
<div th: replace=" /templates/footer : : copy" ></div> 
  • th:object
    用于表单数据对象绑定,将表单绑定到后台controller的一个JavaBean参数。常与th:field一起使用进行表单数据绑定
public class LoginBean implements Serializable{...} 
@RequestMapping(value = "/login", method = RequestMethod.POST) 
public String login(@ModelAttribute(value = "loginBean") LoginBean loginBean,ModelMap model) {...} 
<form id="login-form" th:action="@{/login}" th:object="${loginBean}">...</form> 
  • th:src
    用于外部资源引入,类似于
<script th:src="@{/resources/js/jquery/jquery.json-2.4.min.js}" 
  • th:text
    文本显示
<td class="text" th:text="${username}" ></td> 
  • th:value
    用于标签复制,类似标签的value属性
<option th:value="Adult">Adult</option> 
<input  id="msg" type="hidden" th:value="${msg}" /> 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风水月

从心底相信自己是成功的第一步

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值