JavaEE领域有几种常用的模板引擎: Jsp, Thymeleaf, Freemarker, Velocity等.对于前端页面渲染效率来说 JSP 其实还是最快的, Velocity次之.Thymeleaf虽然渲染效率不是很快,但语法比较轻巧.
Thymeleaf 支持html5标准, Thymeleaf页面无需部署到servlet开发到服务器上,以 .html 后缀结尾,可直接通过浏览器就能打开.可完全替代JSP(前后端分离不是很好).
Thymeleaf可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果.(支持html原型,在html标签增加额外的属性来达到 模板+数据 的展示方式).浏览器解锁html时会忽略未定义的标签属性,模板可以静态运行;当有数据返回到页面时,Thymeleaf标签会动态的替换静态内容,使页面动态显示.
Thymeleaf提供标准和spring标准两种方言,可以直接套用模板实现JSTL,OGNL表达式效果.提供spring标准方言和一个与springMVC完美集成的可选模块,可以快速实现表单绑定,属性编辑器,国际化等功能.
springboot项目默认查找文件位置:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- set thymeleaf version -->
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>
<!--set java version-->
<java.version>1.8</java.version>
</properties>
// 依赖中直接引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
具体配置的参数可以查看org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties
这个类.
@ConfigurationProperties(
prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
private Charset encoding;
private boolean cache;
...
}
在application.properties中可以配置thymeleaf模板解析器属性.就像使用springMVC的 JSP解析器配置一样.下面这些配置实际上就是注入到ThymeleafProperties类中的属性值.
#配置thymeleaf缓存开发期间先关闭,否则影响测试
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML
spring.thymeleaf.check-template-location=true
spring.thymeleaf.servlet.content-type=text/html
controller:
@RestController
@RequestMapping("/thymeleaf")
public class HelloController {
private Logger logger = LoggerFactory.getLogger(HelloController.class);
@GetMapping("index")
public ModelAndView index(ModelMap modelMap){
modelMap.put("userName","Jack");
modelMap.put("date",new Date());
List<Map<String,Object>> list = new ArrayList<>();
Map<String,Object> map1 = new HashMap<>();
map1.put("id",1);
map1.put("name","Tom");
list.add(map1);
Map<String,Object> map2 = new HashMap<>();
map2.put("id",2);
map2.put("name","Marry");
list.add(map2);
modelMap.put("list", list);
return new ModelAndView("hello", modelMap);
}
}
hello.html:
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>springboot-thymeleaftitle>
head>
<body>
<h3>字符串属性h3>
<p th:text="${userName}" />
<h3>日期属性h3>
<p th:text="${#dates.format(date, 'yyyy-MM-dd hh:mm:ss')}" />
<h3>循环h3>
<div th:each="user,userStat :${list}">
<p th:text="'第' + ${userStat.count} + '个用户'">
<p>ID:<span th:text="${user.id}">span>p>
<p>名字:<span th:text="${user.name}">span>p>
div>
<h3>判断1h3>
<div th:switch="${userName}">
<p th:case="'Jack'">存在Jackp>
<p th:case="'Mack'">存在Mackp>
<p th:case="*">不存在任何人p>
div>
<h3>判断3h3>
<span th:if="${userName} == 'Jack'" th:text="${userName}"> span><br />
body>
html>
在使用thymeleaf时首先需要在html标签里引入xmlns:th="http://www.thymeleaf.org"
才能使用 th:*
的语法.
<html lang="en" xmlns:th="http://www.thymeleaf.org">
指令优先级:
Order | Feature | Attributes | remark |
---|---|---|---|
1 | Fragment inclusion | th:insert 、th:replace | 片段包含: jsp:include |
2 | Fragment iteration | th:each | 遍历: c:forEach |
3 | Conditional evaluation | th:if 、th:unless、th:switch、 th:case | 条件判断: c:if |
4 | Local variable definition | th:object 、th:with | 声明变量: c:set |
5 | General attribute modification | th:attr、 th:attrprepend、th:attrappend | 任意属性修改支持prepend,append |
6 | Specific attribute modification | th:value、 th:href、 th:src… | 修改指定属性默认值 |
7 | Text (tag body modification) | th:text 、th:utext | 修改标签体内容. th:text 转义特殊字符, th:utext 不转义特殊字符 |
8 | Fragment specification | th:fragment | 声明片段 |
9 | Fragment removal | th:remove | 删除片段 |
一些常用指令的使用说明:
指令 | 备注 |
---|---|
th:text | 替换原来text中的文本(p,span,div,table) |
th:value | 替换原来value的值(form) |
th:object | 替换标签的对象, th:object="对象" |
th:field | 填充,若外层有对象,可以直接用 *{属性} 取值 |
th:checked | 当值为true时为选中 |
th:remove | 删除 |
th:href | 用 @{...} |
th:if | 值为true时才显示标签 |
th:unless | 值为false时才显示标签 |
th:each | 循环遍历结果集 |
th:style | 替换原有样式 |
th:class | 替换原有class样式 |
th:action | 替换action地址,用 @{...} 取地址 |
th:alt | 用 @{...} 取地址 |
th:fragment | 定义一个fragment模板,后面再引用它 |
<p th:text="'hello, ' + ${name} + '!'">666666p>
需要获取实体类中的属性值时,可以使用 ${对象.属性}
方式获取,这个学JSP时EL表达式一样.注意: $
表达式只在标签内部生效.th:text="${对象.属性名}"
动态显示数据,替换静态值.原先静态值是开发前端时做展示用的.很好的做到了前后端分离.
Thymeleaf通过@{...}
语法来处理URL链接.标签属性有 th:href
和 th:src
.
<a th:href="@{http://www.zhangligong.xyz}">绝对路径a>
<a th:href="@{/}">相对路径a>
<a th:href="@{css/bootstrap.css}">Content路径,默认访问static下文件a>
有时只需要对一段文字中某一处地方进行替换,可以采用字符串拼接 '...'+${对象模.属性}+'...'
或 |... ${对象名.属性}...|
. 注意: |...|
只能包含变量表达式 ${...}
,不能包含其它常量,条件表达式等
<p th:text="'姓名: ' + ${user.name} + '!'">Jackp>
<p th:text="|年龄: ${user.age}!|">18p>
一些算术运算也可以用: +, -, *, div(/) 和 mod(%).
<div th:with="isEven=(${prodStat.count} % 2 == 0)">
这些运算符也可以在OGNL变量表达式内部应用(由OGNL执行):
<div th:with="isEven= ${prodStat.count % 2 == 0}">
逻辑运算符gt(>), lt(<), le(<=), ge(>=), eq(==), neq/ne(!=)都可以使用,XML规定,不得在属性值中使用<
和>
符号,因此应将它们替换为<
和>
。
<div th:if="${prodStat.count} > 1">
<span th:text="'Execution mode is '+((${execMode}=='dev')?'Development':'Production')" />
th:if
当值为true时标签才显示; th:unless
当值为false时标签才显示.
Logina>
thymeleaf支持switch结构,默认属性(default)用*表示.
<div th:switch="${user.role}">
<p th:case="'admin'">User is an administratorp>
<p th:case="#{roles.manager}">User is a managerp>
<p th:case="*">User is some other thingp>
div>
对数据集进行遍历使用 th:each
标签:
<table>
<tr>
<th>NAMEth>
<th>PRICEth>
<th>IN STOCKth>
tr>
<tr th:each="prod : ${prods}">
<td th:text="${prod.name}">Onionstd>
<td th:text="${prod.price}">2.41td>
<td th:text="${prod.inStock}? #{true} : #{false}">yestd>
tr>
table>
Thymeleaf提供了一系列Utility对象(内置于Context中),可以通过#
直接访问.具体API可访问: usingthymeleaf-utility
#{...}
语法获得消息的方式相同。java.util.Date
对象的实用程序方法#dates
,但对于java.util.Calendar
对象String
对象的实用方法id
可能重复(例如,由于迭代的结果)的属性的实用方法<table>
<tr>
<td th:text="${user.id}">1td>
<td th:text="${user.name}">Jacktd>
<td th:text="${user.phone}">136td>
tr>
table>
<table>
<tr th:object="${user}">
<td th:text="*{id}">1td>
<td th:text="*{name}">Jacktd>
<td th:text="*{phone}">136td>
tr>
table>
将后台传入的数据拼接到url中:
<a href="info.html" th:href="@{/user/info(id=${user.id})}">参数拼接a>
<a href="info.html" th:href="@{/user/info(id=${user.id},phone=${user.phone})}">多参数拼接a>
<a href="info.html" th:href="@{/user/info/{uid}(uid=${user.id})}">restful风格a>
<a href="info.html" th:href="@{/user/info/{uid}/abc(uid=${user.id})}">restful风格a>
方式一:
方式二: 使用"|"减少了字符串的拼接
<table>
<tr th:each="user, interStat : ${userList}">
<td th:text="${interStat.index}">td>
<td th:text="${user.id}">td>
<td th:text="${user.name}">td>
<td th:text="${user.phone}">td>
tr>
table>
这里的interStat类似于jstl里面foreach的varStatus,可以获取到当前的迭代信息。interStat里面一些属性的含义:
myMapVal.key相当于map的键,myMapVal.value相当于map中的值。
<div th:each="myMapVal : ${userMap}">
<span th:text="${myMapValStat.count}">span>
<span th:text="${myMapVal.key}">span>
<span th:text="${myMapVal.value.name}">span>
<span th:text="${myMapVal.value.phone}">span>
<br/>
div>
<div th:each="myArrayVal : ${userArray}">
<div th:text="${myArrayVal.name}">div>
<div th:text="${myArrayVal.phone}">div>
div>
条件判断,比如后台传来一个变量,判断该变量的值,0为男,1为女:
<span th:if="${sex} == 0" >
男:<input type="radio" name="sex" th:value="男" />
span>
<span th:if="${sex} == 1">
女:<input type="radio" name="sex" th:value="女" />
span>
*
表示默认,当下面的case都是false的时候,会执行默认的内容。
<div th:switch="${sex}">
<p th:case="0">性别:男p>
<p th:case="1">性别:女p>
<p th:case="*">性别:未知p>
div>
未知
动态设置html标签中的id属性
<span th:id="${uid}">idspan>
从后台传入的uid的值,然后将这个值作为id的值。
类似html标签中的value属性,能对某元素的value属性进行赋值,比如:
<input type="hidden" id="userId" name="userId" th:value="${userId}">
th:inline有三个取值类型:
text: 从后台取出数据展示
<span th:inline="text">Hello, [[${user.nick}]]span>
等同于:
<span>Hello, <span th:text="${user.nick}">span>span>
none: 希望在html中直接显示[[1,2,3],[4,5]],可以使用none
<p th:inline="none"> [[1, 2, 3], [4, 5]]!p>
javascript :希望在JavaScript中获取后台相应的数据
<script th:inline="javascript" type="text/javascript">
var msg = "Hello," + [[${user.phone}]];
alert(msg);
script>
内置对象有#号开始引用.
#request
相当于HttpServletRequest对象, ${#request.getContextPath()}
.
#session
相当于HttpSession对象, ${#session.getAttribute("name")}
.
除了上面的对象外,thymeleaf还提供了功能性对象来处理: