Springboot默认是不支持JSP的,默认使用thymeleaf模板引擎
模板(template fragments)
日常开发中,我们经常会将导航栏,页尾,菜单等部分提取成模板供其它页面使用。
在Thymeleaf 中,我们可以使用th:fragment
属性来定义一个模板。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div th:fragment="commonFooter" class="fly-footer">
<P> <a href="https://blog.csdn.net/weixin_42413153" target="_blank">我的 CSDN 账户</a> </P>
<P> <a href="https://github.com/1093099339" target="_blank">我的 GitHub 账户</a></P>
</div>
</html>
上面定义了一个叫做 commonFooter
的片段,接着我们可以使用th:include
或者th:replace
属性来使用它:
<!-- 脚步区域填充标签 -->
<div th:replace="commmon/footer :: commonFooter"></div>
<!-- or -->
<div th:include="commmon/footer :: commonFooter"></div>
其中th:include中的参数格式为 templatename::[domselector],
其中templatename是模板名(如footer),domselector是可选的dom选择器。
如果只写templatename,不写domselector,则会加载整个模板。
<!-- 也可以这样编写 -->
<div th:include="footer :: (${user.isAdmin}? #{footer.admin} : #{footer.normaluser})"></div>
th:include 是加载模板的内容,而th:replace则会替换当前标签为模板中的标签
例如如下模板:
<footer th:fragment="copy">
© 2016
</footer>
我们通过th:include 和 th:replace来加载模板
<body>
<div th:include="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
</body>
返回的HTML如下:
<body>
<div> © 2016 </div>
<footer>© 2016 </footer>
</body>
模板参数配置
th:fragment定义模板的时候可以定义参数:
<div th:fragment="frag (onevar,twovar)">
<p th:text="${onevar} + ' - ' + ${twovar}">...</p>
</div>
在 th:include 和 th:replace中我们可以这样传参:
<div th:include="::frag (${value1},${value2})">...</div>
<div th:include="::frag (onevar=${value1},twovar=${value2})">...</div>
此外,定义模板的时候签名也可以不包括参数:<div th:fragment="frag">
我们任然可以通过<div th:include="::frag (onevar=${value1},twovar=${value2})">...</div>
这种方式调用模板。这其实和<div th:include="::frag" th:with="onevar=${value1},twovar=${value2}">
起到一样的效果
th:assert 断言
我们可以通过th:assert来方便的验证模板参数
<header th:fragment="contentheader(title)" th:assert="${!#strings.isEmpty(title)}">...</header>
th:remove 删除代码
th:remove的参数有如下几种:
- all 删除当前标签和其内容和子标签
- body 不删除当前标签,但是删除其内容和子标签
- tag 删除当前标签,但不删除子标签
- all-but-first 删除除第一个子标签外的其他子标签
- none 啥也不干
<a href="/something" th:remove="${condition}? tag : none">Link text not to be removed</a>
基本语法
表达式
Variable Expressions: ${...}
Selection Variable Expressions: *{...}
Message Expressions: #{...}
Link URL Expressions: @{...}
Fragment Expressions: ~{...}
获取变量值
<p th:text="'Hello!, ' + ${name} + '!'" >3333</p>
可以看出获取变量值用$符号,对于javaBean的话使用变量名.属性名方式获取,这点和EL表达式一样.
另外$表达式只能写在th标签内部,不然不会生效#{}
是国际化支持取值的符号
注意:th:text与th:utext的区别,输出中文时应该使用th:utext
${..}实际语法是:OGNL(非web),SpEL(web) ,支持的内置变量
用*{...}
选择对象里的变量,如
<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>
基本的
#ctx: the context object.
#vars: the context variables.
#locale: the context locale.
#request: (only in Web Contexts) the HttpServletRequest object.
#response: (only in Web Contexts) the HttpServletResponse object.
#session: (only in Web Contexts) the HttpSession object.
#servletContext: (only in Web Contexts) the ServletContext object.
引入URL
Thymeleaf对于URL的处理是通过语法@{…}
来处理的
<a th:href="@{http://blog.csdn.net/u012706811}">绝对路径</a>
<a th:href="@{/}">相对路径</a>
<a th:href="@{css/bootstrap.min.css}">Content路径,默认访问static下的css文件夹</a>
运算符
在表达式中可以使用各类算术运算符,例如+, -, *, /, %
th:with="isEven=(${prodStat.count} % 2 == 0)"
逻辑运算符>, <, >=, <=,==,!= (gt, lt, ge, le,eq,ne)都可以使用,唯一需要注意的是使用<,>时需要用它的HTML转义符:
th:if="${prodStat.count} > 1"
th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
布尔运算符: and or not/!
条件判断
if/unless
Thymeleaf中使用th:if和th:unless属性进行条件判断,标签只有在th:if中条件成立时才显示,th:unless于th:if恰好相反,只有表达式中的条件不成立,才会显示其内容。
<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>
Switch
Thymeleaf同样支持多路选择Switch结构,默认属性default可以用*表示:
<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>
</di
循环
<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>
迭代对象必须为:
Any object implementing java.util.Iterable、 java.util.Enumeration、java.util.Iterator
Any object implementing java.util.Map. When iterating maps, iter variables will be of class java.util.Map.Entry
.
Any array.
Any other object will be treated as if it were a single-valued list containing the object itself.
<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>
//不过也可以直接加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>
th:each内置迭代状态属性:
index ,当前索引,从0开始。
count,当前数目,从1开始。
size,总大小
current,当前值
even/odd boolean properties.
first boolean property.
last boolean property.
设置html标签属性
<img src="../../images/gtvglogo.png"
th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
//which is equivalent:
<img src="../../images/gtvglogo.png"
th:src="@{/images/gtvglogo.png}" th:title="#{logo}" th:alt="#{logo}" />
//append
<tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? 'odd'">
Thymeleaf 3中的一些变化和特性
文本型模板
文本型模板使得Thymeleaf可以支持输出CSS、Javascript和文本文件。在你想要在CSS或Javascript文件中使用服务端的变量时;或者想要输出纯文本的内容时。
在文本模式中使用Thymeleaf的特性,你需要使用一种新的语法,例如:
[# th:each="item : ${items}"]
- [# th:utext="${item}" /]
[/]
var a = [# th:text="${msg}"/];
增强的内联机制
现在可无需额外的标签,直接在文本中输出数据:
This product is called [[${product.name}]] and it's great!
var a = [[${msg}]];
片段(Fragment)表达式
Thymeleaf 3.0 引入了一个新的片段表达式。形如:~{commons::footer}。
该特性十分有用(比如解决定义通用的header和footer的问题)
base.html
<head th:fragment="common_header(title,links)">
<title th:replace="${title}">The awesome application</title>
<!-- Common styles and scripts -->
<link rel="stylesheet" type="text/css" media="all" th:href="@{/css/awesomeapp.css}">
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
<script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"></script>
<!--/* Per-page placeholder for additional links */-->
<th:block th:replace="${links}" />
</head>
main.html
<head th:replace="base :: common_header(~{::title},~{::link})">
<title>Awesome - Main</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}">
</head>
片段经常和th:insert or th:replace
一起使用
<div th:insert="~{commons :: main}">...</div>
<div th:with="frag=~{footer :: #main/text()}">
<p th:insert="${frag}">
</div>
th:insert and th:replace (and th:include)
的区别:
th:insert 插入片段本身
th:include 与th:insert不同的是,它插入的是片段解析后的内容
无操作标记(token)
Thymeleaf 3.0 另一个新的特性就是无操作(NO-OP no-operation)标记,下划线”_”,代表什么也不做。
例如:
<span th:text="${user.name} ?: _">no user authenticated</span>
//当user.name 为空的时候,直接输出标签体中的内容
Thymeleaf 注释
普通html注释:<!-- User info follows -->
1、<!--/* This code will be removed at Thymeleaf parsing time! */-->
2、<!--/*-->
<div>
you can see me only before Thymeleaf processes me!
</div>
<!--*/-->
3、<!--/*/
<div th:text="${...}">
...
</div>
/*/-->
html内联
//不会转义时
<p>The message is "[(${msg})]"</p>
//等价于
<p>The message is "This is <b>great!</b>"</p>
//转义时
<p>The message is "[[${msg}]]"</p>
//等价于
<p>The message is "This is <b>great!</b>"</p>
//禁用内联
<p th:inline="none">A double array looks like this: [[1, 2, 3], [4, 5]]!</p>
//js内联
<script th:inline="javascript">
...
var username = [[${session.user.name}]];
...
</script>
//css内联
<style th:inline="css">
.[[${classname}]] {
text-align: [[${align}]];
}
</style>