Spring Boot2.0系列教程之模板引擎 Thymeleaf(四)

Spring Boot 推荐使用 Thymeleaf 来代替 JSP,Thymeleaf 模板到底是什么来头呢,下面我们来聊聊。

Thymeleaf 介绍

Thymeleaf 是一款用于渲染 XML/XHTML/HTML 5 内容的模板引擎。类似 JSP、Velocity、FreeMaker 等,它也可以轻易的与 Spring MVC 等 Web 框架进行集成作为 Web 应用的模板引擎。与其他模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

Thymeleaf 特点

简单说,Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点:

  • Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 Thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
  • Thymeleaf 开箱即用的特性。它提供标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式效果,避免每天套模板、改 jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
  • Thymeleaf 提供 Spring 标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。

对比

好了,你们说了我们已经习惯使用了什么 Velocity、FreMaker、Beetle 之类的模版,那么到底好在哪里呢?比一比吧!Thymeleaf 是与众不同的,因为它使用了自然的模板技术。这意味着 Thymeleaf 的模板语法并不会破坏文档的结构,模板依旧是有效的 XML 文档。模板还可以用作工作原型,Thymeleaf 会在运行期替换掉静态值。Velocity 与 FreeMarker 则是连续的文本处理器。

完整代码可在github下载。

https://github.com/zjh746140129/Spring-Boot2.0

项目结构截图:

一、代码片段

1、编写用户类

package com.boot.model;

/**
 * Created by zhoujh on 2018/6/25.
 */
public class User {
    private String name;
    private int age;
    private String pass;

    public User(String name, int age, String pass) {
        this.name = name;
        this.age = age;
        this.pass = pass;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getPass() {
        return pass;
    }

    public void setPass(String pass) {
        this.pass = pass;
    }

    @Override
    public String toString() {
        return ("name=" + this.name + ",age=" + this.age + ",pass=" + this.pass);
    }
}

2、编写controller

package com.boot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by zhoujh on 2018/6/25.
 */
@Controller
public class HelloController {

    @RequestMapping("/")
    public String index(ModelMap map) {
        map.addAttribute("message", "hello thymeleaf");
        return "hello";
    }
}
package com.boot.controller;

import com.boot.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by zhoujh on 2018/6/25.
 */
@Controller
public class DemoController {

    @RequestMapping("/example")
    public String index(ModelMap map) {
        map.addAttribute("userName", "neo");
        map.addAttribute("flag", "yes");
        map.addAttribute("users", getUserList());
        map.addAttribute("type", "link");
        map.addAttribute("pageId", "springcloud/2017/09/11");
        map.addAttribute("img", "aaa.jpg");
        map.addAttribute("count", 12);
        map.addAttribute("date", new Date());
        return "example";
    }


    private List<User> getUserList(){
        List<User> list=new ArrayList<User>();
        User user1=new User("zhangsan",12,"123456");
        User user2=new User("lisi",6,"123563");
        User user3=new User("wangwu",66,"666666");
        list.add(user1);
        list.add(user2);
        list.add(user3);
        return  list;
    }
}
package com.boot.controller;

import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by zhoujh on 2018/6/25.
 */
public class IndexController {


    @RequestMapping("/index")
    public String index() {
        return "index";
    }

    @RequestMapping("/layout")
    public String layout() {
        return "layout";
    }


    @RequestMapping("/home")
    public String home() {
        return "home";
    }
}

3、启动类

package com.boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BootThymeleafApplication {

	public static void main(String[] args) {
		SpringApplication.run(BootThymeleafApplication.class, args);
	}
}

4、页面HTML

一、copyright.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body>
<copyright th:fragment="copyright">
    &copy; 2018
</copyright>
</body>
</html>

二、footer.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body>
<footer th:fragment="footer">
    <h1>我是 尾部</h1>
</footer>

</body>
</html>

三、header.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body>
<header th:fragment="header">
    <h1>我是 头部</h1>
</header>
</body>
</html>

四、left.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <title>left</title>
</head>
<body>
<left th:fragment="left">
    <h1>我是 左侧</h1>
</left>
</body>
</html>

五、example.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <title>Example</title>
</head>
<body>
    <div >
        <h1>text</h1>
        <p th:text="${userName}">neo</p>
        <span th:text="'Welcome to our application, ' + ${userName} + '!'"></span>
        <br/>
        <span th:text="|Welcome to our application, ${userName}!|"></span>
    </div>

    <div >
        <h1>If/Unless</h1>
        <a th:if="${flag == 'yes'}"  th:href="@{/home}"> home </a>
        <br/>
        <a th:unless="${flag != 'no'}" th:href="@{http://www.baidu.com/}" >baidu</a>
    </div>

    <div >
        <h1>for 循环</h1>
        <table>
            <tr  th:each="user,iterStat : ${users}">
                <td th:text="${user.name}">neo</td>
                <td th:text="${user.age}">6</td>
                <td th:text="${user.pass}">213</td>
                <td th:text="${iterStat.index}">index</td>
            </tr>
        </table>
    </div>

    <div >
        <h1>URL</h1>
        <a  th:href="@{http://www.baidu.com/{type}(type=${type})}">link1</a>
        <br/>
        <a href="details.html" th:href="@{http://www.baidu.com/{pageId}/can-use-springcloud.html(pageId=${pageId})}">view</a>
        <br/>
        <div th:style="'background:url(' + @{${img}} + ');'">
            <br/><br/><br/>
        </div>
    </div>

    <div th:inline="text" >
        <h1>内联[ [ ] ]</h1>
        <p>Hello, [[${userName}]]</p>
        <br/>
    </div>

    <div  >
        <h1>内嵌变量</h1>
        <p th:text="${#dates.format(date, 'dd/MMM/yyyy HH:mm')}">neo</p>
        <p th:text="${#dates.createToday()}">neo</p>
        <p th:text="${#dates.createNow()}">neo</p>

        <p th:text="${#strings.isEmpty(userName)}">userName</p>
        <p th:text="${#strings.listIsEmpty(users)}">userName</p>
        <p th:text="${#strings.length(userName)}">userName</p>
        <p th:text="${#strings.concat(userName)}"></p>

        <p th:text="${#strings.randomAlphanumeric(count)}">userName</p>

        <br/>
    </div>

</body>
<script th:inline="javascript">
    var name = [[${userName}]] + ', Sebastian';
  //  alert(name);
</script>
</html>

六、hello.html

<!DOCTYPE html >
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <title>Hello</title>
</head>
<body>
<h1  th:text="${message}">Hello World</h1>
</body>
</html>

七、home.html

<html xmlns:th="http://www.thymeleaf.org"  xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout" layout:decorator="layout">
<head th:include="layout :: htmlhead" th:with="title='Home'"></head>
<body>
    <div  layout:fragment="content" >
        <h2>个性化的内容</h2>
    </div>
</body>
</html>

八、index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
    <title>Index</title>
</head>
<body>
    <div th:include="layout/copyright :: copyright"></div>
    <div th:replace="layout/copyright :: copyright"></div>
</body>
</html>

九、layout.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout">
<head th:fragment="htmlhead">
    <meta charset="UTF-8"></meta>
    <title th:text="${title}!=null?${title}:'Layout'">Layout</title>
</head>
<body>
    <div >
        <div th:replace="layout/header :: header"></div>
        <div th:replace="layout/left :: left"></div>
        <div layout:fragment="content" > content</div>
        <div th:replace="layout/footer :: footer"></div>
    </div>
</body>
</html>

5、配置文件

server.port=8099

6、完整pom 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.boot</groupId>
	<artifactId>boot-thymeleaf</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>boot-thymeleaf</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>RELEASE</version>
        </dependency>
    </dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

二、常用标签语法介绍

1、常用语法

 

①、赋值、字符串拼接

<p th:text="${userName}">neo</p>
<span th:text="'Welcome to our application, ' + ${userName} + '!'"></span>
<span th:text="|Welcome to our application, ${userName}!|"></span>

②、条件判断 If/Unless

Thymeleaf 中使用 th:if 和 th:unless 属性进行条件判断,下面的例子中,<a>标签只有在 th:if 中条件成立时才显示

<a th:if="${flag == 'yes'}"  th:href="@{/home}"> home </a>
<a th:unless="${flag != 'no'}" th:href="@{http://www.ityouknow.com/}" >ityouknow</a>

th:unless 与 th:if 恰好相反,只有表达式中的条件不成立,才会显示其内容。

也可以使用 (if) ? (then) : (else) 这种语法来判断显示的内容 

 

 

③、for 循环

<table>
    <tr  th:each="user,iterStat : ${users}">
        <td th:text="${user.name}">neo</td>
        <td th:text="${user.age}">6</td>
        <td th:text="${user.pass}">213</td>
        <td th:text="${iterStat.index}">index</td>
    </tr>
</table>

iterStat 称作状态变量,属性有

  • index:当前迭代对象的 index(从 0 开始计算)
  • count:当前迭代对象的 index(从 1 开始计算)
  • size:被迭代对象的大小
  • current:当前迭代变量
  • even/odd:布尔值,当前循环是否是偶数/奇数(从 0 开始计算)
  • first:布尔值,当前循环是否是第一个
  • last:布尔值,当前循环是否是最后一个

 

④、URL

URL 在 Web 应用模板中占据着十分重要的地位,需要特别注意的是 Thymeleaf 对于 URL 的处理是通过语法 @{...} 来处理的。 如果需要 Thymeleaf 对 URL 进行渲染,那么务必使用 th:href、th:src 等属性,下面举一个例子:

<a  th:href="@{http://www.ityouknow.com/{type}(type=${type})}">link1</a>

<a href="details.html" th:href="@{http://www.ityouknow.com/{pageId}/can-use-springcloud.html(pageId=${pageId})}">view</a>

 

 

设置背景:

<div th:style="'background:url(' + @{${img}} + ');'">

根据属性值改变背景:

<div class="media-object resource-card-image"  th:style="'background:url(' + @{(${collect.webLogo}=='' ? 'img/favicon.png' : ${collect.webLogo})} + ')'" ></div>

 

几点说明:

  • 上例中 URL 最后的 (pageId=${pageId}) 表示将括号内的内容作为 URL 参数处理,该语法避免使用字符串拼接,大大提高了可读性。
  • @{...} 表达式中可以通过 {pageId} 访问 Context 中的 pageId 变量。
  • @{/order} 是 Context 相关的相对路径,在渲染时会自动添加上当前 Web 应用的 Context 名字,假设 context 名字为 app,那么结果应该是 /app/order。

⑤、内联 [ [ ] ]

内联文本:[[...]] 内联文本的表示方式,使用时,必须先用在 th:inline="text/javascript/none" 激活,th:inline 可以在父级标签内使用,甚至作为 body 的标签。内联文本尽管比 th:text 的代码少,不利于原型显示。

文本内联:

<div th:inline="text" >
    <h1>内联js</h1>
    <p>Hello, [[${userName}]]</p>
    <br/>
</div>

脚本内联,脚本内联可以在 js 中取到后台传过来的参数:

<script th:inline="javascript">
    var name = [[${userName}]] + ', Sebastian';
    alert(name);
</script>

 

 

 

⑥、内嵌变量

为了模板更加易用,Thymeleaf 还提供了一系列 Utility 对象(内置于 Context 中),可以通过 # 直接访问:

  • dates:java.util.Date 的功能方法类
  • calendars: 类似 #dates,面向 java.util.Calendar
  • numbers:格式化数字的功能方法类
  • strings:字符串对象的功能类,contains、startWiths、prepending/appending 等
  • objects:对 objects 的功能类操作
  • bools: 对布尔值求值的功能方法
  • arrays:对数组的功能类方法
  • lists:对 lists 的功能类方法
  • sets
  • maps

下面用一段代码来举例一些常用的方法:

dates
<p th:text="${#dates.format(date, 'dd/MMM/yyyy HH:mm')}">neo</p>
<p th:text="${#dates.createToday()}">neo</p>
<p th:text="${#dates.createNow()}">neo</p>

strings
<p th:text="${#strings.isEmpty(userName)}">userName</p>
<p th:text="${#strings.listIsEmpty(users)}">userName</p>
<p th:text="${#strings.length(userName)}">userName</p>
<p th:text="${#strings.concat(userName)}"></p>

<p th:text="${#strings.randomAlphanumeric(count)}">userName</p>

 

 

 

 

 

2、常用th标签

关键字

功能介绍

案例

th:id

替换id

<input th:id="'xxx' + ${collect.id}"/>

th:text文本替换

<p th:text="${collect.description}">description</p>

th:utext

支html的文本替换<p th:utext="${htmlcontent}">conten</p>
th:object替换对象

<div th:object="${session.user}">

th:value属性赋值

<input th:value="${user.name}" />

th:with变量赋值运算

<div th:with="isEven=${prodStat.count}%2==0"></div>

th:style设置样式

th:style="'display:' + @{(${sitrue} ? 'none' : 'inline-block')} + ''"

th:onclick点击事件

th:οnclick="'getCollect()'"

th:each属性赋值

tr th:each="user,userStat:${users}">

th:if判断条件

<a th:if="${userId == collect.userId}" >

th:unless和th:if判断相反

<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>

th:href链接地址

<a th:href="@{/login}" th:unless=${session.user != null}>Login</a> />

th:switch多路选择 配合th:case 使用

<div th:switch="${user.role}">

th:caseth:switch的一个分支

<p th:case="'admin'">User is an administrator</p>

th:fragment布局标签,定义一个代码片段,方便其它地方引用

<div th:fragment="alert">

th:include布局标签,替换内容到引入的文件

<head th:include="layout :: htmlhead" th:with="title='xx'"></head> />

th:replace布局标签,替换整个标签到引入的文件

<div th:replace="fragments/header :: title"></div>

th:selectedselected选择框 选中

th:selected="(${xxx.id} == ${configObj.dd})"

th:src图片类地址引入

<img class="img-responsive" alt="App Logo" th:src="@{/img/logo.png}" />

th:inline定义js脚本可以使用变量

<script type="text/javascript" th:inline="javascript">

th:action表单提交的地址

<form action="subscribe.html" th:action="@{/subscribe}">

th:remove删除某个属性

<tr th:remove="all">

1.all:删除包含标签和所有的子节点。2.body:不包含标记删除,但删除其所有的子节点。3.tag:包含标记的删除,但不删除它的子节点。4.all-but-first:删除所有包含标签的子节点,除了第一个。5.none:什么也不做。这个值是有用的动态评估

th:attr 设置标签属性,多个属性可以用逗号分隔 比如 th:attr="src=@{/image/aa.jpg},title=#{logo}",此标签不太优雅,一般用的比较少

还有非常多的标签,这里只列出最常用的几个,由于一个标签内可以包含多个th:x属性,其生效的优先级顺序为:

include,each,if/unless/switch/case,with,attr/attrprepend/attrappend,value/href,src ,etc,text/utext,fragment,remove。

 

 

三、实际项目演示

页面布局是最常用的功能之一,不论是前端还是后台都避免不了,使用 Thymeleaf 布局非常简单,下面来演示一下

例子1:我们做一套后台管理系统,我们把index页面需要的css、js封装成一个html,然后在页面直接通过标签引用即可

例子2:Thymeleaf 循环、标签使用

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值