Thymeleaf 入门教程

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}"/>" />

当阅读一个没有解析的JSP页面时,常常很难读懂,简直就是一场视觉灾难!因为JSP并不是真正的HTML,很多web浏览器和编辑器很难对JSP进行解析。

另外,JSP与servlet规范是紧密耦合的,这就意味着它只能使用在以servlet为基础的web应用中。

近年内有涌现出很多要替代JSP作为java应用的视图技术,其中一个有力的竞争者就是:Thymeleaf。Thymeleaf不需要依赖标签库,并且是可编辑的、可以解析到HTML中。另外,它与servlet规范是没有耦合的,因此它可以在JSP不能使用的环境进行使用。下面,我们来看一下如何在Spring MVC中使用Thymeleaf。

1.2 Thymeleaf介绍

  1. Thymeleaf是一个XML/XHTML/HTML5模板引擎,可用于Web与非Web环境中的应用开发。它是一个开源的Java库,基于Apache License 2.0许可。
  2. Thymeleaf提供了一个用于整合Spring MVC的可选模块,在应用开发中,你可以使用Thymeleaf来完全代替JSP或其他模板引擎,如Velocity、FreeMarker等。
  3. Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。
  4. Thymeleaf主要通过HTML的标签属性渲染标签内容,浏览器在解析html时,当检查到Thymeleaf的属性时候会忽略,
  5. 所以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>

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>

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>

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>

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";
}

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">

4.1 基础表达式

4.1.1 变量表达式 ${……}
姓名:<input type="text" name="userName" value="James Carrot" th:value="${person.name}" /><br/>

以上是 html 内容,以下是 java 后台传送数据到前台

/**
 * 入门-thymeleaf基础语法:基础表达式 之 变量表达式
 * 语法:${conten}
 * @param model
 * @return
 */
@RequestMapping("basicExpression")
public String basicExpression(Model model){
    model.addAttribute("person",this.getPerson());
    return "basic_expression";
}
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>

以上是 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";
}
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>

3.properties 文件内容

message.title=\u8fd9\u662f\u4e00\u4e2a\u6807\u9898

4.加入 html 代码

<h1 th:utext="#{message.title}">Hello World</h1>

5.加入 java 代码

/**
 * 入门-thymeleaf基础语法:基础表达式 之 文字国际化 i18n Internationalization
 * 语法:  #{content}
 * 注意点:需要springmvc配置好资源文件,注意中文编码格式
 * @return
 */
@RequestMapping("i18nExpression")
public String i18nExpression(){
    return "i18n_expression";
}

可以看出,在后台代码中,我们没有处理相应的国际化资源文件,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})}">

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";
}

3.注意:当我们在页面中访问服务器资源是,是会被拦截的,需要在 spring 中配置资源处理,才能访问静态资源

<!-- 处理静态资源 -->
<mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>
<mvc:resources mapping="/js/**" location="/js/"/>

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>
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>

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>
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>
    </div>
--------------------------------------------------
    <div>
        <span th:unless="${switch > 8}"> 判断大于8 显示</span>
        <span th:unless="${switch > 32}"> 判断大于32 不显示</span>
    </div>
    <div th:switch="${switch}">
        <p th:case="'admin'">User is an administrator</p>
        <p th:case="30">User is a manager</p>
        <p th:case="20">User is a manager</p>
        <!--默认情况-->
        <p th:case="*">User is some other thing</p>
    </div>
    -- 循环 --
    <div th:if="${personList!=null}">
        <table>
            <tr th:each="person : ${personList}">
                <td th:text="${person.name}"></td>
                <td th:text="${person.age}"></td>
                <td th:text="${person.address}"></td>
            </tr>
        </table>
    </div>
</body>
</html>

5. 项目中的 Thymeleaf

以前一直都是用着 JSP 的,初到公司,发现页面都是 html ,我就带着个疑问,那怎么传数据呢?
刚刚加入项目开发的时候,发现很多数据都是使用JavaScript进行初始化。那也就正常了,但是有些数据是要页面加载时就载入的,那么用什么呢?
这时候原来是模板引擎搞的鬼。
除了以上所展示的标签被运用在项目上,还有其他的在上文未提及到的将在下文讲述。

5.1 项目中被用到的 Thymeleaf 标签 - 片段(th:fragment)

这是我在裂变工具中看到的熟悉的代码,类似于 jsp:include 之类的:
1. editUser.html 定义一个片段

<!-- 用户编辑模态框开始 -->
<div th:fragment="editUserFragment">
….内容
</div>

2.userCenter.html 引用一个片段

<div th:replace="userManager/editUser::editUserFragment"></div>

没错,上面就是我在项目中经常到的所谓类似于包含的标签。我们经常会想要包含在模板片段来自其他模板。
常见的用途是页脚、标题、菜单等。为了做到这一点,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>

引用一个片段

<!-- 传入参数 -->
<div th:replace="param::params(${dataOne},${dataTwo})"></div>

文档编写 by chuIllusions

猜你喜欢

转载自blog.csdn.net/sinat_30254575/article/details/79515222