一、使用

  本篇文章将以SpringBoot为框架来介绍Thymeleaf的用法。

  1 资源文件的约定目录结构 

Maven的资源文件目录:/src/java/resources
spring-boot项目静态文件目录:/src/java/resources/static
spring-boot项目模板文件目录:/src/java/resources/templates
spring-boot静态首页的支持,即index.html放在以下目录结构会直接映射到应用的根目录下:

classpath:/META-INF/resources/index.html
classpath:/resources/index.html
classpath:/static/index.html
calsspath:/public/index.html

  因此,SpringBoot默认的静态资源文件应该放在resources/tatic下,而静态页面应该放在resources/templates文件夹下,这两个文件不会自动创建,需要手动创建,如下图所示:

  2 Maven依赖:

         <!-- thymeleaf 前端渲染模板依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>

  3 html页面中(<html>标签处):

 <html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">

  4 application.properties配置(application.yml则根据格式相应变化即可):

 # THYMELEAF (ThymeleafAutoConfiguration)
#开启模板缓存(默认值:true)
spring.thymeleaf.cache=true
#Check that the template exists before rendering it.
spring.thymeleaf.check-template=true
#检查模板位置是否正确(默认值:true)
spring.thymeleaf.check-template-location=true
#Content-Type的值(默认值:text/html)
spring.thymeleaf.content-type=text/html
#开启MVC Thymeleaf视图解析(默认值:true)
spring.thymeleaf.enabled=true
#模板编码
spring.thymeleaf.encoding=UTF-8
#要被排除在解析之外的视图名称列表,用逗号分隔
spring.thymeleaf.excluded-view-names=
#要运用于模板之上的模板模式。另见StandardTemplate-ModeHandlers(默认值:HTML5)
spring.thymeleaf.mode=HTML5
#在构建URL时添加到视图名称前的前缀(默认值:classpath:/templates/)
spring.thymeleaf.prefix=classpath:/templates/
#在构建URL时添加到视图名称后的后缀(默认值:.html)
spring.thymeleaf.suffix=.html
#Thymeleaf模板解析器在解析器链中的顺序。默认情况下,它排第一位。顺序从1开始,只有在定义了额外的TemplateResolver Bean时才需要设置这个属性。
spring.thymeleaf.template-resolver-order=
#可解析的视图名称列表,用逗号分隔
spring.thymeleaf.view-names=

  配置好以上的代码,此时在html模板文件中动态的属性使用th:命名空间修饰,就可以使用Thymeleaf了。

二、语法

  1 引用静态资源文件:

    比如CSS和JS文件,语法格式为“@{}”,如@{/js/blog/blog.js}会引入/static目录下的/js/blog/blog.js文件。

  2 访问spring-mvc中model的属性:

    语法格式为“${}”,如${user.id}可以获取model里的user对象的id属性,类似JSTL。

  3 循环:

    在html的标签中,加入th:each=“value:${list}”形式的属性,如<span th:each=”user:${users}”></span>可以迭代users的数据

  4 判断:    

在html标签中,加入th:if=”表达式”可以根据条件显示html元素

 <span th:if="${not #lists.isEmpty(blog.publishTime)}">
  <span id="publishtime" th:text="${#dates.format(blog.publishTime, 'yyyy-MM-dd HH:mm:ss')}"></span>
</span>

以上代码表示若blog.publishTime时间不为空,则显示时间。

5 时间格式化:

 ${#dates.format(blog.publishTime,'yyyy-MM-dd HH:mm:ss')} //表示将时间格式化为”yyyy-MM-dd HH:mm:ss”格式化写法与Java格式化Date的写法是一致的。 

  6 字符串拼接:

    有两种形式 ,比如拼接这样一个URL:/blog/delete/{blogId}

第一种:th:href="'/blog/delete/' + ${blog.id }"
第二种:th:href="${'/blog/delete/' + blog.id }"

7 为CSS样式的某些路径使用thyemleaf表达式:

 <div th:style="'background:url(' + @{/<path-to-image>} + ');'"></div>

   8 使用th:utext="@{}" 可以让变量里面的html标签被解析

三、表达式

  1 简单表达式 (simple expressions)

   ${...} 变量表达式

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

   #{...} 消息表达式

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

  2 字面量

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

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

   true false 布尔类型

   null 空

   one,sometext,main 文本字符

  3 文本操作

   + 字符串连接

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

  4 算术运算

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

   - 负号(一元运算符)

  5 布尔操作

   and,or 二元操作符

   !,not 非(一元操作符)

  6 关系操作符

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

   == , != (eq, ne)

  7 条件判断

 (if) ? (then) if-then

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

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

条件表达式中的三个部分自身也可以是表达式,也可以是变量(${...}, *{...}), 消息(#{...}), URL (@{...}) 或字面量 ('...')
条件表达式也可以使用括号来嵌套:

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

  else表达式也可以省略,当条件为false时,会返回null:

 <tr th:class="${row.even}? 'alt'">
...
</tr>
(value) ?: (defaultvalue) Default

  只有在第一个表达式返回null时,第二个表达式才会运算

  8 表达式工具对象

 #dates 与java.util.Date对象的方法对应,格式化、日期组件抽取等等
#calendars 类似#dates,与java.util.Calendar对象对应
#numbers 格式化数字对象的工具方法
#strings 与java.lang.String对应的工具方法:contains、startsWith、prepending/appending等等
#objects 用于对象的工具方法
#bools 用于布尔运算的工具方法
#arrays 用于数组的工具方法
#lists 用于列表的工具方法
#sets 用于set的工具方法
#maps 用于map的工具方法
#aggregates 用于创建数组或集合的聚合的工具方法
#messages 用于在变量表达式内部获取外化消息的工具方法,与#{…}语法获取的方式相同
#ids 用于处理可能重复出现(例如,作为遍历的结果)的id属性的工具方法

  9 链接URL

URL在web模板中是一级重要元素,使用@{…}表示

URL的类型:

  绝对URL:

http://www.thymeleaf.org

  相对URL:

 页面相对: user/login.html
上下文相对:/itemdetails?id=3 (服务器上下文名称会被自动添加)
服务器相对:~/billing/processInvoice(允许调用同一服务器上的另一个上下文中的URL)
协议相对://code.jquery.com/jquery-2.0.3.min.js

Thymeleaf在任何情况下都可以处理绝对URL,对于相对URL,则需要使用一个实现了IWebContext接口的上下文对象,这个对象包含了来自HTTP请求的信息,这些信息用于创建相对链接。

 <!-- 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>

  10 预处理
  Thymeleaf提供预处理表达式的功能。

它是在表壳式正常执行前执行的操作,允许修改最终将要被执行的表达式。

预处理表达式跟正常的一样,但被两个下划线包围住,例如:__${expression}__

假设有一个i18n消息文件Message_fr.properties,里面有一个条目包含了一个调用具体语言的静态方法的OGNL表达式:

article.text=@myapp.translator.Translator@translateToFrench({0})

  Messages_es.properties中的等价条目:

article.text=@myapp.translator.Translator@translateToSpanish({0})

  可以根据locale先创建用于运算表达式的标记片段,本例中,先通过预处理选择表达式,然后让Thymeleaf处理这个选择出来的表达式:

<p th:text="${__#{article.text('textVar')}__}">Some text here...</p>

  对于locale为French的情况,上面的表达式经过预处理后,得出的等价物如下:

<p th:text="${@myapp.translator.Translator@translateToFrench(textVar)}">Some text here...</p>

四、 设置属性值

  1 th:attr 任何属性值

 <form action="subscribe.html" th:attr="action=@{/subscribe}">
  <fieldset>
    <input type="text" name="email" />
    <input type="submit" value="Subscribe me!" th:attr="value=#{subscribe.submit}"/>
  </fieldset>
</form>

  多个属性一起设置,用逗号隔开

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

  2 设置指定属性

th:abbr
th:accept
th:accept-charset
th:accesskey
th:action
th:align
th:alt
th:archive
th:audio
th:autocomplete
th:axis
th:background
th:bgcolor
th:border
th:cellpadding
th:cellspacing
th:challenge
th:charset
th:cite
th:class
th:classid ...
 <input type="submit" value="Subscribe me!" th:value="#{subscribe.submit}"/>
<form action="subscribe.html" th:action="@{/subscribe}">
<li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>

  设置多个属性在同一时间 有两个特殊的属性可以这样设置: th:alt-title 和 th:lang-xmllang

th:alt-title 设置 alt 和 title
th:lang-xmllang 设置 lang 和 xml:lang

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

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

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

  前置和后置添加属性值 th:attrappend 和 th:attrprepend

<input type="button" value="Do it!" class="btn" th:attrappend="class=${' ' + cssStyle}" />

  编译后:

<input type="button" value="Do it!" class="btn warning" />

  还有两个特定的添加属性 th:classappend 和 th:styleappend

<tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? 'odd'">

  3 修复的布尔属性

<input type="checkbox" name="active" th:checked="${user.active}" />

  所有修复的布尔属性:

th:async
th:autofocus
th:autoplay
th:checked
th:controls
th:declare
th:default
th:defer
th:disabled
th:formnovalidate
th:hidden
th:ismap
th:loop
th:multiple
th:novalidate
th:nowrap
th:open
th:pubdate
th:readonly
th:required
th:reversed
th:scoped
th:seamless
th:selected

  HTML5友好的属性及元素名

 <table>
<tr data-th-each="user : ${users}">
<td data-th-text="${user.login}">...</td>
<td data-th-text="${user.name}">...</td>
</tr>
</table>

  注:data-{prefix}-{name}是编写HTML5自定义属性的标准语法,不需要开发者使用th:*这样的命名空间,Thymeleaf让这种语法自动对所有dialect都可用。

五、遍历

  1 基础

 <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>

  可遍历的对象:实现java.util.Iterable、java.util.Map(遍历时取java.util.Map.Entry)、array、任何对象都被当作只有对象自身一个元素的列表

  2 状态

当前遍历索引,从0开始,index属性
当前遍历索引,从1开始,count属性
总元素数量,size属性
每一次遍历的iter变量,current属性
当前遍历是even还是odd,even/odd布尔属性
当前遍历是第一个,first布尔属性
当前遍历是最后一个,last布尔属性

 <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>

若不指定状态变量,Thymeleaf会默认生成一个名为“变量名Stat”的状态变量:

 <tr th:each="prod : ${prods}" th:class="${prodStat.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>

六、条件运算

 <tr th:each="prod : ${prods}" th:class="${prodStat.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>
  <td>
    <span th:text="${#lists.size(prod.comments)}">2</span> comment/s
    <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:if="${not #lists.isEmpty(prod.comments)}">view</a>
  </td>
</tr>
<a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:if="${not #lists.isEmpty(prod.comments)}">view</a>

  th:if 不只运算布尔条件,它对以下情况也运算为true:

  值不为null
    值为boolean且为true
    值为数字且非0
    值为字符且非0
    值是字符串且不是:“false”,“off”,“no”
    值不是boolean、数字、字符、字符串
  如果值为null,则th:if运算结果为false

  th:if的反面是th:unless

 <a href="comments.html" th:href="@{/comments(prodId=${prod.id})}" th:unless="${#lists.isEmpty(prod.comments)}">view</a>
th:switch 和 th:case <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> <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>

七、坑

  总结一下在使用过程中遇到的坑:

  1 获取项目根目录,很多时候我们都需要获取本项目的根目录,但是使用的代码是以下代码才能获得:

<script th:inline="javascript" type="text/javascript">
var ctx=[[${#httpServletRequest.getContextPath()}]];
</script>

  注意以上代码,如果需要在自定义的javascript中使用thymeleaf表达式,则需要将script声明一下:th:inline="javascript"。

  2 获取图片路径,当我们使用thymeleaf的时候一定要注意单、双引号的区别,不然是无法获取到对应的值或者路径的:

<span class="img" th:style="'background-image: url('+@{/images/news/}+${top4News[2].originArticleId}+'/1.jpg'+');'"></span>

  请注意以上代码:当我们要在backgroud-image这个标签下引用对应路径的img时:

    首先使用th:style进行修饰。

    然后在background-image标签前后一定要加单引号,否则不会起作用:

'background-image:xxx'

    接着就是在url里面拼接你的img路径,请注意url('xxx'),也有单引号!

    最后才能通过此路径获取到相应的图片。

八、总结

  在使用thymeleaf的过程中,遇到了一些坑,希望大家在这样的坑中少走一些弯路。

前端渲染模板(一):Thymeleaf的更多相关文章

  1. JsRender 前端渲染模板基础学习

    JsRender前端渲染模板 使用模板,可以预先自定义一些固定格式的HTML标签,在需要显示数据时,再传入真实数据组装并展示在Web页中:避免了在JS中通过“+”等手动分割.连接字符串的复杂过程:针对 ...

  2. 云平台项目--学习经验--jsrender前端渲染模板

    jsrender的好处:可以预先自定义一些固定的html标签,在需要显示数据的时候,可以直接传入真实的数据并显示在web页面中,避免了Js编写中的复杂过程:针对高性能和纯字符串渲染并优化,不需要依赖D ...

  3. JsRender 前端渲染模板常用API学习

    JsRender 常用API 1. $.templates() $.templates()方法是用来注册或编译模板的,使用的情况有以下几种. 把html字符串编译编译成模板 获取使用script标签声 ...

  4. Django框架之前端渲染-模板层

      Django 模板层   Django 模板层 前后端数据传递 (1) 后端朝前端页面传递数据的方式: # 将当前所在的名称空间中的名字全部传递给前端页面 # 第一种 return render( ...

  5. 前端渲染利器——JsRender入门

    JsRender不少前端人员应该都用过,它是一个比较强大的模板,不牵涉太多技术依赖,使用起来非常舒服.我本人在前端开发中使用React之前,都是用的它了(实际上我感觉React没有JsViewes好用 ...

  6. vue前端渲染和thymeleaf模板渲染冲突问题

    vue前端渲染和thymeleaf模板渲染冲突问题 话不多说直接上现象: 解决办法: 在此做个记录吧,说不定以后会碰到 <<QIUQIU&LL>>

  7. 新一代Java模板引擎Thymeleaf

    新一代Java模板引擎Thymeleaf-spring,thymeleaf,springboot,java 相关文章-天码营 https://www.tianmaying.com/tutorial/u ...

  8. SpringBoot入门系列(四)整合模板引擎Thymeleaf

    前面介绍了Spring Boot的优点,然后介绍了如何快速创建Spring Boot 项目.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/ ...

  9. 【大前端之前后分离01】JS前端渲染VS服务器端渲染

    前言 之前看了一篇文章:@Charlie.Zheng Web系统开发构架再思考-前后端的完全分离,文中论述了为何要前后分离,站在前端的角度来看,是很有必要的:但是如何说服团队使用前端渲染方案却是一个现 ...

随机推荐

  1. oracle 触发器序列号自增

    步骤:1.创建表 table 2.创建序列 SEQUENCE 3.创建 触发器 截图实例:

  2. SQL SERVER先判断视图是否存在然后再创建视图的语句

    如果我们的语句为: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 IF NOT EXISTS(SELECT 1 FROM sys.views WHERE name='Report_I ...

  3. python 小点

    python中列表不能除以列表,列表不能除以整数.浮点数. numpy数组可以实现数组除以整数.

  4. OCP 12c最新考试原题及答案(071-6)

    6.(4-21) choose the best answer: View the Exhibit and examine the structure of the CUSTOMERS table. ...

  5. 剑指offer面试题1---赋值运算符函数

    题目描述:如下类型CMyString的声明,请为该类型添加赋值运算符函数. class CMyString{public:    CMyString(char* pData = NULL);    C ...

  6. 参照跟老男孩学linux运维搭建nagios实验小结

        nagios效果示例 http://192.168.0.236/nagios       用户名:hong     密码:123   一. 服务端安装准备   1. 更新源 cd /etc/y ...

  7. heap与stack的区别

    java 的内存分为两类,一类是栈内存,一类是堆内存.栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这 ...

  8. (USB HID) VC++ 使用 SetupAPI 操作 USB HID Device

    在VC裡頭使用 Api必須include 跟加入 lib,加入之後就可以在VC裡頭任意使用api了 暫時先貼上程式碼...等待有空時候在更新說明 extern "C" { #inc ...

  9. Machine learning 吴恩达第二周coding作业(必做题)

    1.warmUpExercise: function A = warmUpExercise() %WARMUPEXERCISE Example function in octave % A = WAR ...

  10. 海思3519A 移植 Qt 5.5.1

    源码下载 网址:qt-everywhere-opensource-src-5.5.1.tar.gz 配置生成MakeFile 文件 解压源码包,在源码包路径下生成配置 MakeFile : ./con ...