Spring Boot2学习笔记--thymeleaf

摘要

看完本文你将掌握如下知识点:

项目准备

依赖

<!--spring对thymeleaf的支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

开启spring boot对thymeleaf的支持

##thymeleaf
spring.thymeleaf.enabled=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML
#关闭页面缓存
spring.thymeleaf.cache=false
spring.thymeleaf.servlet.content-type=text/html

也可以通过@Bean的方式开启支持

    @Bean
    public ThymeleafViewResolver thymeleafViewResolver(){
        log.info("thymeleafViewResolver");
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        viewResolver.setOrder(1);
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setContentType("text/html");
        viewResolver.setCache(false);
        return viewResolver;
    }

    @Bean
    public SpringResourceTemplateResolver templateResolver(){
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(this.applicationContext);
        templateResolver.setPrefix("classpath:/templates/");
        templateResolver.setSuffix(".html");        
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCacheable(false);
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine(){
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        templateEngine.setEnableSpringELCompiler(true);
        return templateEngine;
    }

开启html页面对thymeleaf语法的支持

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

语法

各种表达式语法

1.${...} 变量表达式,用于展示后台传递过来的变量(request和session中的值)

<input type="text" name="modify" th:value="${modify}"/>
<input type="text" name="id" th:value="${dataObj.id}"/>
<textarea  name="logParamData" id="logParamData" th:text="${dataObj.logParamData}"></textarea>

以下两种方式效果一致
<span th:text="${dataObj.name}"></span>
<span>[[${dataObj.name}]]</span>

字符串拼接,可以使用加号,也可以使用竖线,以下两种方式效果一致
<input type="checkbox" name="accessTypes" th:value="${item.id}+'_'+${type.id}" checked="checked"> [[${type.name}]
<input type="checkbox" name="accessTypes" th:value="${|${item.id}_${type.id}|}" checked="checked"> [[${type.name}]

#dates与java.util.Date对象的方法对应,格式化、日期组件抽取等等
<td th:text="${#dates.format(item.logTime, 'yyyy-MM-dd')}"></td>
<td>[[${#dates.format(item.logTime, 'yyyy-MM-dd')}]]</td>

2.#{...} 国际化消息表达式,用于展示message.properties等国际化资源文件中的内容

<input type="checkbox" name="selectAll" id="selectAll" th:text="#{common.choose}"/>

消息中需要传递变量的情况,多个变量逗号分割
<strong th:text="#{common.page.summary(${_pageBean.pageCount},${_pageBean.total})}">

以下两种方式效果一致
<td th:text="#{common.operate}"></td>
<td>[[#{common.operate}]]</td>

3.@{...} 链接url表达式,用于封装url,如contextPath补全

<link th:href="@{/resource/css/netqin.css}" rel="stylesheet"/>
用两个竖线来拼接带表达式的字符串
<script type="text/javascript" th:src="@{|/resource/js/i18n/list.#{locale}.js|}"></script>
带请求参数的url,多个用逗号分割
<a th:href="@{/auth/systemLogger/edit.do(id=${item.id},flag=${flag})}" th:text="#{common.edit}"></a>

4.js和css中用到表达式时使用双中括号的方式

var modify = "[[${modify}]]";
if(modify != "add"){
    $("#password").attr("placeholder","[[#{user.detail.changeNotice}]]");
}

5.*{...} 选择变量表达式,用于简写变量名称,需要配合th:object一起使用

<div th:object="${user}">
    <p>firstName: <span th:text="*{firstName}"></span></p>
    <p>lastName: <span th:text="*{lastName}"></span></p>
</div>
相当于
<div>
    <p>firstName: <span th:text="${user.firstName}"></span></p>
    <p>lastName: <span th:text="${user.lastName}"></span></p>
</div>

6.~{...} 代码块表达式,用于在html中复用相同的结构
语法:~{templatename::fragmentname}
示例:
common/model.html,th:fragment="header"指定代码块名称

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="header">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<META http-equiv="Pragma" content="no-cache">
<META http-equiv="Cache-Control" content="no-cache">
<META http-equiv="Expire" content="0">
<link th:href="@{/resource/css/bootstrap.min.css}" rel="stylesheet" />
<link th:href="@{/resource/css/ace.min.css}" rel="stylesheet" />
<link rel="stylesheet" th:href="@{/resource/css/font-awesome.min.css}" />
<script th:src="@{/resource/js/jquery-1.11.0.min.js}"></script>
</head>
<body>
</body>
</html>

demo.html,th:replace="common/model::header",模板名称::代码块名称

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<header th:replace="common/model::header"></header>
<body>
</body>
</html>

说明:代码块表达式需要配合th属性(th:insert,th:replace,th:include)一起使用。

th:insert:将代码块片段整个插入到使用了th:insert的HTML标签中,
th:replace:将代码块片段整个替换使用了th:replace的HTML标签中,
th:include:将代码块片段包含的内容插入到使用了th:include的HTML标签中,

遍历

简单示例

<tr th:each="item:${results}">
<td>
    <input type="checkbox" name="ids" th:value="${item.id}" class="noborder"/>
</td>
<td th:text="${item.id}"></td>
<td>
    [[${#dates.format(item.logTime, 'yyyy-MM-dd')}]]
</td>
<td th:text="${item.logDesc}"></td>
<td th:text="${item.logUser}"></td>
</tr>

带遍历状态的示例

<tr th:each="item,status:${results}" th:class="${status.odd}? 'odd':'even'">
<td>
    <input type="checkbox" name="ids" th:value="${item.id}" class="noborder"/>
</td>
<td th:text="${item.id}"></td>
<td>
    [[${#dates.format(item.logTime, 'yyyy-MM-dd')}]]
</td>
<td th:text="${item.logDesc}"></td>
<td th:text="${item.logUser}"></td>
</tr>
  • 状态说明
  index:当前遍历索引,从0开始
  count:当前遍历索引,从1开始
  size:总元素数量
  current:每一次遍历的iter变量
  even/odd:当前遍历是even还是odd,布尔属性
  first:当前遍历是第一个,布尔属性
  last:当前遍历是最后一个,布尔属性

遍历时可以自定义变量

th:with:用于定义变量,多个使用逗号分割
<span th:each="type,status:${accessTypes}" th:with="shwoName=${item.id}+'_'+${item.name}">
[[${shwoName}]]
<span th:if="${not status.last}">,</span>  
</span>

条件判断

th:if

判断为true时才会显示div,authorities为Set类型,所以判断是否包含时可以使用#sets.contains()方法,测试时发现使用#arrays.contains()方法时也可以
<div th:if="${dataObj.reserved}">
    <li th:each="item:${dataObj.authorities}">
        <input type="checkbox" name="authorities" th:value="${item.id}"
              th:if="${dataObj.authorities ==null or not #sets.contains(dataObj.authorities,item)}">
        <input type="checkbox" name="authorities" th:value="${item.id}"
              checked="checked" th:if="${dataObj.authorities !=null and #sets.contains(dataObj.authorities,item)}">
        <span th:text="${item.showNameRole}"></span>
    </li>
</div>

如果要判断为false时才会显示div,可以判断值是否等于false,或者使用th:unless
<div th:if="${dataObj.reserved==false}">
    <li th:each="item:${dataObj.authorities}">
        <input type="checkbox" name="authorities" th:value="${item.id}"><span th:text="${item.showNameRole}"></span>
    </li>
</div>

<div th:unless="${dataObj.reserved}">
    <li th:each="item:${dataObj.authorities}">
        <input type="checkbox" name="authorities" th:value="${item.id}"><span th:text="${item.showNameRole}"></span>
    </li>
</div>

  • th:if 以下情况运算为true
  值不为null
  值为boolean且为true
  值为数字且非0
  值为字符且非0
  值是字符串且不是:“false”,“off”,“no”
  值是object,但不为null

th:switch 和 th:case

bool匹配
<div th:switch="${dataObj.reserved}">
    <p th:case="true">true</p>
    <p th:case="false">false</p>
</div>

字符串匹配,要加单引号
<div th:switch="${item.showNameRole}">
    <p th:case="'admin'">administrator</p>
    <p th:case="'manager'">manager</p>
</div>

<div th:switch="${item.showNameRole}">
    <p th:case="'admin'">administrator</p>
    <p th:case="'manager'">manager</p>
    <p th:case="*">unknow</p>
</div>


  • 说明:th:case="*" 表示没有匹配成功时显示的内容

运算符

  • 字符串连接
  + : ${item.id}+'_'+${type.id}
  |xxxx| : |The name is ${name}|
  • 算术运算
  + , - , * , / , %  (二元运算符)
  -  :负号(一元运算符)
  • 布尔操作
  and :且,or :或 (二元运算符)
  !,not :非(一元操作符)
  • 关系操作符
  > , < , >= , <= (gt , lt , ge , le)
  == , != (eq, ne)

表达式工具对象

  #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属性的工具方法

使用springsecurity权限标签的方法

添加依赖

<!--如果项目中使用到了springsecurity4, 则要加入下面的依赖来使用权限标签-->
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity4</artifactId>
    <version>3.0.2.RELEASE</version>
</dependency>

开启命名空间支持

<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
</html>

使用方式与jsp标签类似:
<a th:href="@{/auth/systemLogger/edit.do}" class="btn btn-success btn-xs no-hover" th:text="#{common.create}" sec:authorize="hasRole('LOGGER_ADD')"></a>
<button class="btn btn-danger btn-xs" id="delete" th:text="#{common.delete}" sec:authorize="hasRole('LOGGER_DELETE')"></button>

调用spring管理的bean的方法

语法:${@beanName.methodName(param,...)}
说明:beanName就是注册时的名称
示例:

#httpSession就是javax.servlet.http.HttpSession对象
#httpServletRequest就是javax.servlet.http.HttpServletRequest对象
<span th:text="${@commonService.clearSessionMessage(#httpServletRequest)}" style="display: none"></span>

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容