SpringBoot之使用thymeleaf模板

背景

以前写前端页面都是通过jsp写的,但是由于SpringBoot最后会打成jar包,所以不支持jsp,而使用纯html页面会给开发带来非常大的困难,因此需要引入模板引擎

市面上的模板引擎非常多,譬如:jspVelocityFreemarkerThymeleaf

而SpringBoot推荐的是Thymeleaf模板

引入Thymeleaf

要想使用Thymeleaf模板首先应该先准备环境,而引入Thymeleaf的环境也非常简单,只需要引入相应的starter即可

在pom.xml中导入相关依赖

<!-- 引入Thymeleaf模板 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

使用Thymeleaf模板的规则

Themeleaf写在HTML页面中的,那么Thymeleaf要怎样才能识别我们写的HTML文件呢?我们可以就看下 ThymeleafProperties 类中的一段代码

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

   private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;

   public static final String DEFAULT_PREFIX = "classpath:/templates/";

   public static final String DEFAULT_SUFFIX = ".html";

可以看到有两个属性分别是DEFAULT_PREFIX跟DEFAULT_SUFFIX,即默认的前缀跟默认的后缀,也就是说我们返回的字符串会被默认得到添加上前缀跟后缀,比如我们返回了一个login字符串,最后会被拼成classpath:/templates/login.html,也即是说我们只要将我们的HTML页面放到类路径下的templates目录下就能够被Thymeleaf渲染

基本使用

上面已经讨论了只要我们将我们的HTML页面放到类路径下的templates目录下就可以被Thymeleaf渲染,那么怎样去使用它呢?

首先我们需要导入Thymeleaf的名称空间,这样做的目的是能够在使用Thymeleaf语法的时候有语法提示

<html xmlns:th="http://www.thymeleaf.org">

之后就可以在HTML页面里面使用Thymeleaf语法了

<!-- th:text: 将div里面的内容替换 -->
<div th:text="${hello}"></div>

Thymeleaf语法规则

th语法

在Thymeleaf模板中也有许多th标签,它比较类似于JSTL标签,能够帮我们完成很多诸如循环、判断等功能,不过他们是"寄生"在HTML标签上的

下图是相关的th标签以及它们之间的优先级关系

th:fragment & th:insert & th:replace & th:include

这几个标签时引用公共片段的时候使用的,例如在网页上的某一个或几个部分是不变的,那么为了减少代码量,就可以将这些片段抽取出来做成公共片段,而抽取的公共片段用th:fragment来声明,引入的时候用th:insert、th:replace或th:include引入即可

1、抽取公共片段

将相同的部分抽取出去

<div th:fragment="copy">
    © 2011 The Good Thymes Virtual Grocery
</div>

2、引入公共片段

<div th:insert="~{footer :: copy}"></div>

在要引入的地方将这些公共片段引入,而引入的方式有两种

①、 ~{templatename::selector}:模板名::选择器 

  • 模板名:即公共片段放置的文件路径
  • 选择器:即公共片段所在标签的id,选择器的写法为 #idName

②、 ~{templatename::fragmentname}:模板名::片段名 

  • 模板名:依旧是公共片段放置的文件路径
  • 片段名:即th:fragment后面跟的名字

介绍了引入片段的两种方式后,接下来就要介绍引入片段的三个标签了

  • th:insert:会将整个公共片段插入到所引入的标签里面
  • th:replac:将所在的标签替换成公共标签
  • th:include:将所在的标签替换成公共片的最外层标签,也就是将公共片段的最外层标签去掉插入到所映入的标签中

下面分别对这三个标签的效果进行演示,引入之前的公共片段

<body>
    ...
    <div th:insert="footer :: copy"></div>
    <div th:replace="footer :: copy"></div>
    <div th:include="footer :: copy"></div>
</body>

插入之后的效果

<body>
    ...
    <div>
        <footer>
            © 2011 The Good Thymes Virtual Grocery
        </footer>
    </div>

    <footer>
        © 2011 The Good Thymes Virtual Grocery
    </footer>

    <div>
        © 2011 The Good Thymes Virtual Grocery
    </div>
</body>

3、引入片段时传入参数

在公共片段中添加参数(通过小括号的方式添加参数)

<div th:replace="commons/bar::#sidebar(activeUri='emps')"></div>

然后在引入的时候就可以获取在公共片段中设置的值(注意:这个值可以设置到th:fragment标注的标签的里面使用)

<nav th:fragment="topbar">
    <a th:class="${activeUri=='main' ? 'nav-link active' : 'nav-link'}"></a>
</nav>

th:each

遍历标签,用在标签上可以循环指定次数的当前标签

<tr th:each="item : ${items}">
    <td th:text="${item.name}"></td>
    <td th:text="${item.age}"></td>
</tr>

th:if

条件判断,如果判断成立,那么显示所在标签,如果判断不成立,不加载当前标签

<div th:if="${param == 0}"></div>

如果param等于0,那么div显示,否则div不会被加载

th:unless

跟th:if的判断相反,即如果结果正确当前的标签不会加载,反之加载

<div th:unless="${session.user != null}"></div>

如果session.user为空,结果为真,则div不会显示。否则加载

th:switch & th:case

显示switch的值跟case对应的标签

<div th:switch="${session.user}">
  <p th:case="'jinxin'">call me jinxin</p>
  <p th:case="'timo'">call me timo</p>
</div>

switch里面session.user的值是哪一个就显示哪一个p标签

th:object

替换对象,直接用属性名调用对象里面的属性

<div th:object="${session.user}">
    <p th:text="*{name}"></p>
    <p th:text="*{age}"></p>
</div>

不用通过对象点出属性的方式调用,直接写属性即可

th:with

th:with可以用来定义局部变量

<div th:with="User = ${session.user}">
    <p th:text="User.name"></p>
</div>

th:attr & th:attrprepend & th:attrappend

th:attr可以设置属性的值,还可以配合"|"对属性值拼接,还可以设置多个属性的值,多个属性之间用逗号隔开。而th:attrprepend可以给一个属性前面附加值,th:attrappend给一个属性后面附加值,例如在给class设置值的时候,class已经有一个类名为con了,还想再设置一个style的类名,就可以使用这两个标签添加

<!-- th:attr -->
1、写死的单个属性值添加  
th:attr="src=@{/hello(l='jjj')}"  
2、写死的多个属性值添加  
th:attr="src=@{/hello(l='jjj')}, class=con"  
3、当一个属性的值较多的时候可以用 |   
th:attr="class=|btn btn-group|"  


<!-- th:attrappend -->
th:attrappend="class=${' ' + con}" />


<!-- th:attrprepend -->
th:attrprepend="class=${cssStyle+' '}"

th:value & th:href & th:title & ...

th后面跟上html标签自带的属性可以替换掉原来对应的属性

th:text & th:utext

改变当前标签体里面的内容,th:text会转义特殊字符,th:utext不会转义

还可以在标签体里面添加[[  ]]或者[(  )]来代替th:text跟th:utext

<div th:text="${msg}"></div>
<div th:utext="${msg}"></div>

[[ ${msg} ]]
[( ${msg} )]

th:remove

th:remove可以删除标签,它有如下几个属性

  1. all:删除包含标签和所有的孩子。
  2. body:不包含标记删除,但删除其所有的孩子。
  3. tag:包含标记的删除,但不删除它的孩子。
  4. all-but-first:删除所有包含标签的孩子,除了第一个。
  5. none:什么也不做。

表达式语法

变量表达式:${}

用于获取变量的值,底层是OGNL

${}能够获取那些值?

1、获取对象的属性、调用方法

2、还能使用内置的基本对象

  • #ctx :当前的上下文对象
    • ${#ctx.locale}
    • ${#ctx.variableNames}
    • ${#ctx.request}
    • ${#ctx.response}
    • ${#ctx.session}
    • ${#ctx.servletContext}
  • #vars:当前上下文里面的变量值
  • #locale:区域信息
    • ${#locale.country}
  • #requestrequest对象
    • ${#request.getAttribute('foo')}
    • ${#request.getParameter('foo')}
    • ${#request.getContextPath()}
    • ${#request.getRequestName()}
    • ...
  • #responseresponse对象
  • #sessionsession对象
    • ${#session.getAttribute('foo')}
    • ${#session.id}
    • ${#session.lastAccessedTime}
    • ...
  • #servletContextservletContext对象
    • ${#servletContext.getAttribute('foo')}
    • ${#servletContext.contextPath}
    • ...

3、内置的一些工具对象

  • #execInfo
  • #messages
  • #uris
  • #conversions
  • #dates
  • #calendars
  • #numbers
  • #strings
  • #objects
  • #bools
  • #arrays
  • #lists
  • #sets
  • #maps
  • #aggregates
  • #ids

变量的选择表达式:*{}

${}表达式效果一样,但是有一个补充功能

我们如果需要打印一个对象中的属性,会像下面这样:

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

上面可以看到从session中取出user对象然后一个一个的打印里面的属性,这样有点麻烦,那么这时候就可以利用*来代替上面的session.user对象,即:

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

Message表达式:#{}

获取国际化内容

Link URL表达式: @{...}

用来定义URL的,不需要再在URL后面通过问号去拼参数了,而是将所有的参数写在小括号里面,多个参数用逗号隔开

@{/order/process(execId=${execId}, execType='FAST')}

Fragment表达式: ~{...}

片段引用的表达式

<div th:insert="~{commons :: main}">...</div>
posted @ 2018-09-11 15:36  Jin同学  阅读(912)  评论(0编辑  收藏  举报