随着互联网技术的发展,页面静态化的需求越来越明显,传统的jsp动态页面逐渐的被html静态页面+ajax异步请求所替代,模板技术解决了静态页面的数据更新问题。这篇博客主要是结合spring boot 来介绍一下 thymeleaf模板技术。
thymelaaf的特点:
a.html格式,
模板直接交给浏览器渲染。
b.实现真正意义上的前后端分离,
在标签上引用了thymeleaf表达式后,当页面被浏览器解析后,标签内原有的内容将被表达式的值替换,前端人员只需要将页面演示内容填写好,后台人员你需要要编写正确的表达式返回正确的值,页面就能达到想要的效果。
c.页面即原型,所见即所得
在Web开发过程中一个绕不开的话题就是前端工程师与后端工程师的协作,在传统Java Web开发过程中,前端工程师和后端工程师一样,也需要安装一套完整的开发环境,然后各类Java IDE中修改模板、静态资源文件,启动/重启/重新加载应用服务器,刷新页面查看最终效果。
但实际上前端工程师的职责更多应该关注于页面本身而非后端,使用JSP,Velocity等传统的Java模板引擎很难做到这一点,因为它们必须在应用服务器中渲染完成后才能在浏览器中看到结果,而Thymeleaf从根本上颠覆了这一过程,通过属性进行模板渲染不会引入任何新的浏览器不能识别的标签,例如JSP中的<form:input>
,不会在Tag内部写表达式。整个页面直接作为HTML文件用浏览器打开,几乎就可以看到最终的效果,这大大解放了前端工程师的生产力,它们的最终交付物就是纯的HTML/CSS/JavaScript文件。
1.依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
spring boot 默认会将templates目录映射为模板目录,因此你只需要讲你的模板放在templates目录下即可。
2.配置
添加了上述依赖之后,spring boot实际上为我们初始化了很多基本配置,我们只需要简单的配置一下页面类型即可,这些配置都简单易懂:
#thymeleaf start
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false #关闭页面缓存,这样才能实时的看到页面更改
#thymeleaf end
然后你就可以开始编写你的页面模板了,但是需要注意,为了让thymeleaf识别一个模板,你必须使用下面的html头标签:
<html xmlns:th="http://www.thymeleaf.org">
...
</html>
这样thymeleaf才能真缺德解析!
3.语法
3.1 引入普通文本,数字 th:text
尽管使用模板动态的为页面添加普通文本并没有什么意义,但是还是值得一提,铜鼓他,我们将引入thymeleaf中一个常用的标签th:text="文本内容";
这个标签的作用就是将文本内容填充到表达式作用的标签内:例如在模板中这样写
<p th:text="'你好,thymeleaf~~~"> hello world!</p>
显示到页面的效果为:
3.2引入html代码
通th:text的方式,我们只能想页面引入纯文本,即便是你提供的是带有html格式的代码,thymeleaf也会将他解析为普通的文本,不过,我们可以通过th:utext标签来为页面引入html,这样thymeleaf就会将文本内容解析为html代码并交给浏览器渲染,例如:
<p th:utext="'lt;font color=\'red\'> 你好,thymeleaf~~~>/font>'"> hello world!</p>
效果:
不过需要注意的是,<,>这两个标签符号由于会和已有的html中标签产生冲突,所以需要用html预定义符号<,>代替。
3.3 变量
在thymeleaf中,可以使用${变量名}来向页面中引入一个变量:
<h1 th:text="'hello,' + ${name} + '!'">测试文本!</h1>
controller代码:
@RequestMapping("/hello")
public String hello(Model model) {
System.out.println("一个访问...");
model.addAttribute("name", "thymeleaf");
return "hello";
}
当我们访问action时,页面效果为:

3.4 url
<img alt="测试图片" th:src="@{http://www.thymeleaf.org/images/thymeleaf.png}" width="120" height="120"/>

你也可以使用相对路径:th:href=@{user/login.action}
<a th:href="@{user/login.action}">转到登录页面</a>
或者
<a th:href="@{./user/login.action}">转到登录页面</a>
上面两种心事的路径被解析后的结果都为:http://localhost:9020/start/test/user/login.action
3.5 Url参数拼接:
// 多个参数键值对用','隔开
<a th:href="@{/user/login.action(id=${user.id},name=${user.name})}" >用户信息</a>
解析后的url为:
/start/user/login.action?id=111&name=bug4j
thymeleaf会自动加上相应的?与&,
3.6 消息表达式#{...}
消息表达式允许你再模板页面上读取消息源里面的静态内容,消息源可以是配置文件,数据库等,消息配置文件实际就是一个properties文件,文件内容为key=value形式的键值对。
如果你使用spring boot的默认配置,那么配置文件的名称为messages.properties,他必须放在resource根目录下,这样thymeleaf才能找到。
消息表达式常用于加载静态文本内容,之所以吧静态内容提取为消息,是为了能方便的集中管理页面上某些可能会变动的内容。
例子:
配置文件:
页面内容:
<p>
<h1 th:text="#{home.hello}">你好,这是一条消息</h1>
</p>
访问效果:

另外,thymeleaf还支持在文件名上指定语言的消息配置文件,例如,要想某个配置文件只对中文有效,可以将配置文件的名称命名为:messages_zh_CN.properties,那么,当你的操作系统的的语言为简体中文时,你访问页面是页面内的消息将从这个带有语言表示的消息源中读取。
3.7 对象选择表达式:
和变量表达式一样,对象选择表达式也可以从一个对象中获取某个特定的值使用,而且他的语法与变量表达式完全一致,不同的是,对象选择表达式必须从父标签中声明的对象中获取内容,而不是从任意对象中获取。
因此,要想使用对象选择表达式,你必须通过th:object在要使用的元素标签的父标签上获取到内容源对象:格式为:th:object ect="${...}".例如:
<p th:object="${user}">
<h1 th:text="'标号:'+*{id}">id</h1>
<h1 th:text="'姓名:'+*{name}">name</h1>
<h1 th:text="'性别'+*{sex}">sex</h1>
</p>
页面效果为:
4.运算符
thymeleaf中支持java中的各类运算符如+,-,*,/,%等,也支持各类逻辑运算符,如>,<,>=,<=,==,!=等,甚至java中的三目运算符?都可以使用,不过需要注意的是,<,>这两个运算符由于会和html中标签产生冲突,所以需要用html预定义符号<,>代替。
例如:
<p>3等于4吗?答案是:<span th:text="3==4?'正确':'错误'">答案</span></p>
<p>50大于30吗?答案是:<span th:text="50 > 30?'正确':'错误'">答案</span></p>
页面结果为:

5.条件判断if/unless:
条件判断if/unlesse可以根据某个调价是否成立来控制标签内容是否显示,
if:当if条件成立时,内容显示,例如:
<p th:if="${user.id} > 1">用户的id大为111,于1,所以能显示这些</p>
而页面显示的结果为:

<p th:unless="${user.name == null }">当“用户名称为空”这个条件不成立就显示,
用户名为:<span th:text="${user.name}">用户名</span></p>
页面解过为:
6.循环 th:each:
<tr th:each="user : ${users}" align="center">
<td th:text="${user.id}">666</td>
<td th:text="${user.name}">name</td>
<td th:text="${user.sex}">sex</td>
</tr>
得到的结果为:
7.分支条件判断表达式:th:switch
<div th:switch="${user.name}">
<h1><p th:case="bug4j">他是博主</p></h1>
<h1><p th:case="liuyifei">这是博主女朋友</p></h1>
<h1><p th:case="*">你是游客</p></h1>
</div>
结果是:

当然,你可以用 * 表示没有选项匹配是的默认值,类似于java中的default.
8.Utilities工具集
8.1 基本内置对象:
基本内置对象类似于jsp的内置对象,基本上就是将域对象转换了个形式,基本内置对象一共有如下几个:
- #ctx:上下文对象。
- #vars: 上下文变量。
- #locale:上下文语言环境。
- #request:(只在Web上下文中)HttpServletRequest对象。
- #response:(只在Web上下文中)HttpServletResponse对象。
- #session:(只在Web上下文中)HttpSession对象。
- #servletContext:(只在Web上下文中)ServletContext对象。
你的操作系统语言环境为:
<span th:text="${#locale.language}"></span>,<span th:text="${#locale.displayCountry}"></span>,<span th:text="${#ctx.locale}"></span>
页面效果为:

8.2 表达式工具对象
- #execInfo:关于正在处理的模板的信息。
- #messages:在变量表达式中获得外部化消息的方法,与使用#{...}语法获得的方式相同。
- #uris:用于转义URL / URI部分的方法
- #conversions:执行配置的转换服务的方法(如果有的话)。
- #dates:java.util.Date对象的方法:格式化,组件提取等
- #calendars:类似于#dates,但是对于java.util.Calendar物体。
- #numbers:格式化数字对象的方法。
- #strings:String对象的方法:contains,startsWith,prepending / appending等
- #objects:一般对象的方法。
- #bools:布尔评估的方法。
- #arrays:数组的方法。
- #lists:列表的方法。
- #sets:套的方法。
- #maps:map集合的方法。
- #aggregates:在数组或集合上创建聚合的方法。
- #ids:处理可能重复的id属性的方法(例如,作为迭代的结果)。
// controller代码
Date today = new Date();
model.addAttribute("today", today);
模板代码:
今天是:<span th:text="${#calendars.format(today,'yyyy 年 MM 月 dd 日')}">xxxx年xx月xx日</span>
页面效果为:

更多关于thymeleaf的用法请参见:thymeleaf官方文档