Thymeleaf 使用分享
1. Thymeleaf简介
1.1 Thymeleaf使用背景
虽然JSP已经使用了较长的时间,并且在Java web中使用的也很广泛,但是它也有自身的一些缺陷。明显的就是JSP是以HTML或者XML的形式展现的。大多数的JSP模版都使用HTML的格式,并使用各种JSP标签库。虽然这些标签库可以在JSP中进行动态的解析,但是却很难有一个格式良好的页面。比如,可以在HTML中使用下面的JSP标签:
<input type="text" value="<c:out value="${thing.name}"/>" />
- 1
当阅读一个没有解析的JSP页面时,常常很难读懂,简直就是一场视觉灾难!因为JSP并不是真正的HTML,很多web浏览器和编辑器很难对JSP进行解析。
另外,JSP与servlet规范是紧密耦合的,这就意味着它只能使用在以servlet为基础的web应用中。
近年内有涌现出很多要替代JSP作为java应用的视图技术,其中一个有力的竞争者就是:Thymeleaf。Thymeleaf不需要依赖标签库,并且是可编辑的、可以解析到HTML中。另外,它与servlet规范是没有耦合的,因此它可以在JSP不能使用的环境进行使用。下面,我们来看一下如何在Spring MVC中使用Thymeleaf。
1.2 Thymeleaf介绍
- Thymeleaf是一个XML/XHTML/HTML5模板引擎,可用于Web与非Web环境中的应用开发。它是一个开源的Java库,基于Apache License 2.0许可。
- Thymeleaf提供了一个用于整合Spring MVC的可选模块,在应用开发中,你可以使用Thymeleaf来完全代替JSP或其他模板引擎,如Velocity、FreeMarker等。
- Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。
- Thymeleaf主要通过HTML的标签属性渲染标签内容,浏览器在解析html时,当检查到Thymeleaf的属性时候会忽略,
- 所以Thymeleaf的模板可以通过浏览器直接打开展现,这样非常有利于前后端的分离。
2. SpringMVC + Thymeleaf 整合使用
搭建好SpringMVC开发环境后,接下来就可以整合Thymeleaf模板引擎。
2.1 Thymeleaf 添加 Maven 依赖
在pom.xml中添加以下依赖
<dependencies>
<!-- ========= Thymeleaf模板引擎 ========== -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
</dependencies>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
2.2 Thymeleaf 整合 SpringMVC 环境准备
为了在Spring中使用Thymeleaf,需要配置3个bean:
1. ThymeleafViewResolver:用来从逻辑视图中解析出Thymeleaf模版;
2. SpringTemplateEngine:对模版进行处理,并给出结果;
3. TemplateResolver:用来加载Thymeleaf模版;
2.2.1 在 SpringMVC 配置文件中删除原有配置文件中,对 JSP 的解析配置
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
- 1
- 2
- 3
- 4
- 5
2.2.2 新增 Thymeleaf 配置
<!-- 模板解析器 -->
<bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
<!-- 模板文件的路径前缀 -->
<property name="prefix" value="/templates/" />
<!-- 模板文件的路径后缀 -->
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML" />
<!-- 配置是否缓存 -->
<!-- 默认情况下, 模板缓存为true。如果您想要设置为false -->
<property name="cacheable" value="false" />
<!-- 默认编码格式 -->
<property name="characterEncoding" value="UTF-8"/>
</bean>
<!-- 模板引擎 -->
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="enableSpringELCompiler" value="true" />
</bean>
<!-- 视图解析器 -->
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<property name="characterEncoding" value="UTF-8"/>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
2.2.3 创建模板文件夹,在 webapp 下创建 templates 文件夹放置 .html 模板文件
3. 入门 Demo 先睹为快
3.1 在templates目录下新建thymeleaf.html,内容如下:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>认识 ThymeLeaf 模板引擎</title>
</head>
<body>
<h1 th:text="${model}">Hello World</h1>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
3.2 在 Controller 中 传入数据
/**
* 这是入门程序,先睹为快,展示thymeleaf能做什么
* 经过程序的执行,跟我们以前使用的JSP中EL表达式非常相像
* @param request
* @param model
* @return
*/
@RequestMapping("myThymeleaf")
public String myThymeleaf(HttpServletRequest request, Model model){
model.addAttribute("model","初认识Thymeleaf模板引擎");
return "thymeleaf";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
3.3 使用感觉
1. 模板使用非常简单,在原有的 html 标签中,使用 th: 前缀就可以像 EL 表达式或 JSP 标签库与后台数据进行动态交互;
2. Thymeleaf模版不像JSP,它是可以编辑甚至可以自然的解析,不需要准备其他任何处理过程;
3. 可以看到,前端开发人员可以直接修改html并直接观察修改后的效果,修改时并不影响Thymeleaf的代码,因此可以方便前后端协同开发。
4. Thymeleaf 基本语法
在 html 文件中使用 Thymelead 标签 需要在头文件中加入,否则无法使用它的标签
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
- 1
- 2
4.1 基础表达式
4.1.1 变量表达式 ${……}
姓名:<input type="text" name="userName" value="James Carrot" th:value="${person.name}" /><br/>
- 1
以上是 html 内容,以下是 java 后台传送数据到前台
/**
* 入门-thymeleaf基础语法:基础表达式 之 变量表达式
* 语法:${conten}
* @param model
* @return
*/
@RequestMapping("basicExpression")
public String basicExpression(Model model){
model.addAttribute("person",this.getPerson());
return "basic_expression";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
4.1.2 选择/星号表达式 *{……}
<div th:object="${person}">
<p>Name:
<span th:text="*{name}">Saturn</span>.
</p>
<p>Age:
<span th:text="*{age}">30</span>.
</p>
<p>Phone:
<span th:text="*{phone}">1350992····</span>.
</p>
<p>Address:
<span th:text="*{address}">广州**科技</span>.
</p>
</div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
以上是 html 内容,以下是 java 后台传送数据到前台
/**
* 入门-thymeleaf基础语法:基础表达式 之 选择/星号表达式
* 语法: *{content}
* 注意点: 需要配合th:object标签使用
* @param model
* @return
*/
@RequestMapping("selectExpression")
public String selectExpression(Model model){
model.addAttribute("person",this.getPerson());
return "basic_expression_selection";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
4.1.3 文字国际化表达式 #{……}
Thymeleaf文字国际化需要springmvc的支持
1. 在资源目录 resources 下创建文件夹 spring-i18n 作为国际化文件的根目录,创建各种语言的 .properties文件存储需要使用的内容
2. 在 spring 配置文件中加入资源
<!--配置thymeleaf文字国际化 -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<!-- 资源文件路径 -->
<property name="basename" value="spring-i18n/messages"></property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
3.properties 文件内容
message.title=\u8fd9\u662f\u4e00\u4e2a\u6807\u9898
- 1
4.加入 html 代码
<h1 th:utext="#{message.title}">Hello World</h1>
- 1
5.加入 java 代码
/**
* 入门-thymeleaf基础语法:基础表达式 之 文字国际化 i18n Internationalization
* 语法: #{content}
* 注意点:需要springmvc配置好资源文件,注意中文编码格式
* @return
*/
@RequestMapping("i18nExpression")
public String i18nExpression(){
return "i18n_expression";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
可以看出,在后台代码中,我们没有处理相应的国际化资源文件,Thymeleaf会自动根据浏览器语言,从spring管理的国际化资源文件中选中合适的进行显示。
4.1.4 URL表达式 @{……}
@{……}支持决定路径和相对路径。其中相对路径又支持跨上下文调用url和协议的引用。
1.html 代码
URL点击 :<a href="details.html" th:href="@{myThymeleaf(orderId=${id})}">view</a></br>
相对路径:<img th:width="100px" th:src="@{../images/{imageUrl}(imageUrl=${image})}"></br>
绝对路径:<img th:width="100px" th:src="@{/images/{imageUrl}(imageUrl=${image})}"></br>
<!-- 无效链接 -->
其他路径:<img th:width="100px" th:src="@{images/{imageUrl}(imageUrl=${image})}">
- 1
- 2
- 3
- 4
- 5
2.java 代码
/**
* 入门-thymeleaf基础语法:基础表达式 之 url
* 语法: @{content}
* 注意:对静态资源的处理,否则访问不到
* @param model
* @return
*/
@RequestMapping("urlExpression")
public String urlExpression(Model model){
model.addAttribute("id",10);
model.addAttribute("image","001.jpg");
return "url_expression";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
3.注意:当我们在页面中访问服务器资源是,是会被拦截的,需要在 spring 中配置资源处理,才能访问静态资源
<!-- 处理静态资源 -->
<mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>
<mvc:resources mapping="/js/**" location="/js/"/>
- 1
- 2
- 3
4.2 Thymeleaf 常用标签
4.2.1 普通标签
Thymeleaf中大部分标签都是与html原有属性对应的,比如html中script标签的src属性,在Thymeleaf中对应th:src标签,这样通过静态解析的时候,浏览器会读取src属性对应的js,而通过动态解析访问的时候,浏览器拿到的src即为th:src中的内容。
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>常用普通标签-ThymeLeaf 模板引擎</title>
</head>
<body>
<!--
Thymeleaf中大部分标签都是与html原有属性对应的,比如html中script标签的src属性,在Thymeleaf中对应th:src标签
-->
<!-- 引入iuput标签 -->
<input type="text" name="name" th:value="ThymeleafValue" value="HtmlValue">
<!-- 引入img标签 -->
<img src="../images/001.jpg" width="200px" th:width="100px" th:src="@{../images/001.jpg}"></br>
<!-- 引用javascript标签 -->
<script type="text/javascript" src="../js/myThymeleaf.js" th:src="@{/js/myThymeleaf.js}"></script>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
4.2.2 常用标签
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>常用普通标签-ThymeLeaf 模板引擎</title>
</head>
<body>
<!--
Thymeleaf中大部分标签都是与html原有属性对应的,比如html中script标签的src属性,在Thymeleaf中对应th:src标签
-->
<p>简单数据转换:</p>
<dt>年龄</dt>
<!-- 此示例表示保留两位小数位,整数位1位,不够位自动补0; -->
<dd th:text="${#numbers.formatDecimal(person.age, 1, 2)}">25</dd>
<dt>生日</dt>
<dd th:text="${#dates.format(person.birthday, 'yyyy-MM-dd')}">2014-12-01</dd>
<p>字符串拼接</p>
<dt>地址</dt>
<dd th:text="${'广东省'+person.address}">越秀区</dd>
<p>表单</p>
<form th:action="@{/vic/person}" th:object="${person}" method="post" th:method="post">
<!-- th:field常用于表单字段绑定。通常与th:object一起使用。 属性绑定、集合绑定。 -->
<dt>姓名:<input type="text" th:field="*{name}"/></dt>
<dt>年龄:<input type="text" th:field="*{age}"/></dt>
<dt>电话:<input type="text" th:field="*{phone}"/></dt>
<dt>地址:<input type="text" th:field="*{address}"/></dt>
<dt>生日:<input type="text" th:field="*{birthday}"/></dt>
<dt><input type="submit"/>
</form>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
th:field 表单字段的绑定是经常使用的。方便开发
4.2.3 常用工具
工具对象表达式。常用于日期、集合、数组对象的访问。这些工具对象就像是java对象,可以访问对应java对象的方法来进行各种操作。有#maps、#dates、#calendars、#numbers、#lists等
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>工具对象-ThymeLeaf 模板引擎</title>
</head>
<body>
<p>工具对象表达式。常用于日期、集合、数组对象的访问。
这些工具对象就像是java对象,可以访问对应java对象的方法来进行各种操作。</p>
<p>#maps、#dates、#calendars、#numbers、#lists等</p>
<p>简单数据转换:</p>
<dt>#numbers:年龄</dt><dd th:text="${#numbers.formatDecimal(person.age, 1, 2)}">25</dd>
<dt>#dates:生日</dt><dd th:text="${#dates.format(person.birthday, 'yyyy-MM-dd')}">2014-12-01</dd>
<dt>#calendars:生日</dt><dd th:text="${#calendars.format(person.birthday, 'dd MMMM yyyy')}">2014-12-01</dd>
<div th:if="${#maps.isEmpty(persons)}">
<p>#maps:判断对象是否为空</p>
</div>
<div>
#lists:<span th:text="${#lists.size(personList)}"></span>
</div>
<!-- 变量必须在里面使用,否则无效 -->
<div th:with="sizes=${#lists.size(personList)}">
<h3>当前数据长度:<span th:text="${sizes}"></span></h3>
</div>
<div>
<!-- 此参数必须经过地址栏传到 -->
#httpServletRequest: <span th:text="${#httpServletRequest.getParameter('ids')}"></span>
</div>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
4.2.3 循环、IF、Switch
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>IF/EACH/SWITCH-ThymeLeaf 模板引擎</title>
</head>
<body>
<div>
<span th:if="${switch > 8}"> 判断大于8 显示</span>
<span th:if="${switch > 32}"> 判断大于32 不显示</span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
5. 项目中的 Thymeleaf
以前一直都是用着 JSP 的,初到公司,发现页面都是 html ,我就带着个疑问,那怎么传数据呢?
刚刚加入项目开发的时候,发现很多数据都是使用JavaScript进行初始化。那也就正常了,但是有些数据是要页面加载时就载入的,那么用什么呢?
这时候原来是模板引擎搞的鬼。
除了以上所展示的标签被运用在项目上,还有其他的在上文未提及到的将在下文讲述。
5.1 项目中被用到的 Thymeleaf 标签 - 片段(th:fragment)
这是我在裂变工具中看到的熟悉的代码,类似于 jsp:include 之类的:
1. editUser.html 定义一个片段
<!-- 用户编辑模态框开始 -->
<div th:fragment="editUserFragment">
….内容
</div>
- 1
- 2
- 3
- 4
2.userCenter.html 引用一个片段
<div th:replace="userManager/editUser::editUserFragment"></div>
- 1
没错,上面就是我在项目中经常到的所谓类似于包含的标签。我们经常会想要包含在模板片段来自其他模板。
常见的用途是页脚、标题、菜单等。为了做到这一点,Thymeleaf需要我们定义包含可用的片段,我们可以通过使用th:fragment标签
userManager/editUser是要引入页面的路劲加上去掉后缀的名称
editUserFragment就是dom选择器,即为th:fragment中的值
通过使用th:include or th:replace or th:insert 属性之一都可以使用片段
对于片段的灵活运用,那么就是对它进行参数传递
定义一个片段
<meta charset="utf-8" pageEncoding="utf-8"/>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<!-- 用户编辑模态框开始 -->
<div th:fragment="params(one,two)">
<p th:text="${one}"></p>
<p th:text="${two}"></p>
</div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
引用一个片段
<!-- 传入参数 -->
<div th:replace="param::params(${dataOne},${dataTwo})"></div>
- 1
- 2