Spring Boot学习笔记(五)Web开发之Thymeleaf模板引擎

2019-04-14 08:22发布

一、Thymeleaf简介以及引入

Spring Boot推荐使用Thymeleaf模板引擎来做前端动态页面,它用来替代jsp。
模板引擎作用:
我们先编写一个前端页面模板,页面模板上需要动态数据的写上模板引擎规定的表达式,然后模板引擎解析后端传入的数据,根据前端页面模板上的表达式,将数据填充到页面模板上的指定位置,形成动态页面。
在这里插入图片描述 Thymeleaf简介:
Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎。类似JSP,Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。与其它模板引擎相比,Thymeleaf最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个Web应用。Thymeleaf旨在提供⼀个优雅的、⾼度可维护的创建模板的⽅式。 为了实现这⼀⽬标,Thymeleaf建⽴在⾃然模板的概念上,将其逻辑注⼊到模板⽂件中,不会影响模板设计原型。
Thymeleaf引入(Maven):
Spring Boot有专门的starter引入Thymeleaf:spring-boot-starter-thymeleaf,可以去Spring Boot官方文档starter章节查看。 org.springframework.boot spring-boot-starter-thymeleaf 3.0.9.RELEASE 2.2.2 Thymeleaf使用:
我们去找autoconfigure.jar包里的org.springframework.boot.autoconfigure.thymeleaf包下的ThymeleafAutoConfiguration类,它是Thymeleaf的自动配置类 @Configuration @EnableConfigurationProperties(ThymeleafProperties.class) @ConditionalOnClass(TemplateMode.class) @AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class }) public class ThymeleafAutoConfiguration { @EnableConfigurationProperties(ThymeleafProperties.class)引入了Thymeleaf的配置类,有关Thymeleaf的相关配置都在这 @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"; /** * Prefix that gets prepended to view names when building a URL. */ private String prefix = DEFAULT_PREFIX; /** * Suffix that gets appended to view names when building a URL. */ private String suffix = DEFAULT_SUFFIX; /** * Template mode to be applied to templates. See also Thymeleaf's TemplateMode enum. */ private String mode = "HTML"; 从这就可以知道只要把HTML页面放在classpath:/templates/目录下,thymeleaf就能自动渲染。这些配置我们可以在配置文件中使用spring.thymeleaf改掉。
我们在写thymeleaf页面模板的的时候需要导入名称空间: 如果使用eclipse开发需要安装Thymeleaf插件才能有提示功能。
1、在线安装:
方法一:点击Help>Install New Software>add,然后Location输入http://www.thymeleaf.org/eclipse-plugin-update-site/;name随意。然后一路next即可。
方法二:点击Help>Eclipse Marketplace,输入Thymeleaf查找,找到后点击Install。
2、离线安装:
方法一:下载Thymeleaf插件,点击Help>Install New Software>add,点击Location选择插件压缩包,然后一路next。插件下载链接: https://pan.baidu.com/s/1C-GtRUcGzvr7GzZMMvDFeQ 提取码: wknb。
方法二:下载Thymeleaf插件解压,然后再eclipse安装目录下新建一个文件夹,将Thymeleaf插件解压后的文件放入这个文件夹中,再新建一个links文件夹,新建Thymeleaf.link文件,里面内容: path=D:/Eclipse-SpringTools/sts-bundle/sts-3.7.1.RELEASE/myplugins/thymeleaf-extras-eclipse-plugin-2.1.2 然后重启eclipse即可。

二、Thymeleaf语法简介

Thymeleaf官网下载Thymeleaf官方文档(https://www.thymeleaf.org/documentation.html) 选择3.0版本的pdf下载即可。或者下载中文文档,链接: https://pan.baidu.com/s/1z5hbKIN3xRoLf1QncblKmA 提取码: 8qqm
Thymeleaf简单示例: Test
这是显示欢迎信息
这章示例来源:Thymeleaf官方文档。

1、th语法

1.1 设置属性值

(1)设置任何属性:
可以使用th:attr来设置,多个属性中间使用逗号分隔,示例: 属性也可以使用:th:任意html属性,来设置。作用和上面一样。它可以用来替换原生属性的值(即使在标准⽅⾔中没有为其定义特定的th:*处理器)。示例: 推荐使用第二种方式的写法。 (2)前缀和后缀
Thymeleaf还提供th:attrprepend和th:attrappend属性,它们为现有属性值设置前缀和后缀。 Thymeleaf标准⽅⾔中还有两个特定的附加属性:th:classappend和th:styleappend属性,⽤于将CSS类或样式⽚段添加到元素中,⽽不覆盖现有属性。示例: (3)固定值的布尔属性
HTML具有布尔属性的概念,这个布尔属性没有值,并且⼀旦这个布尔属性存在则意味着属性值为“true”。但是在XHTML中,这些属性只取⼀个值,这个属性值就是它本身。例如:checked,selected等 Thymeleaf标准⽅⾔允许您通过计算条件表达式的结果来设置这些属性的值,如果条件表达式结果为true,则该属性将被设置为其固定值,如果评估为false,则不会设置该属性。 (4)HTML5友好属性语法
hymeLeaf还⽀持HTML5友好属性语法来处理模版。
... ...
data-th-each相当于th:each。

1.2 循环

(1)基本语法
ThymeLeaf使用th:each语法来进行循环遍历,相当于jsp中的c:forEach。示例: Onions 2.41 yes 我们称$ {prods}迭代表达式或被迭代变量;prod为迭代变量或简单的iter变量。,prod iter变量的作⽤域为元素,这意味着它可⽤于内部标记,如。
(2)迭代状态
当使⽤th:each时,Thymeleaf提供了⼀种⽤于跟踪迭代状态的机制:状态变量。状态变量在每个th:each属性中定义,并包含以下数据:
  • 当前迭代索引,从0开始。这是index属性。
  • 当前的迭代索引,从1开始。这是count属性。
  • 迭代变量中元素的总量。 这是size属性。
  • 每次迭代的iter变量。 这是current属性。
  • 当前的迭代是偶数还是奇数。 这些是even/odd布尔属性。
  • 当前的迭代是否是第⼀个迭代。 这是first布尔属性。
  • 当前的迭代是否是最后⼀个迭代。 这是last布尔属性。
    示例:
Onions 2.41 yes 迭代状态变量(本示例中的iterStat)在th:each属性中通过在iter变量本身之后直接写其名称来定义,⽤逗号分隔。 就像iter变量⼀样,状态变量的作⽤范围也是th:each属性的标签定义的代码⽚段中。如果没有显式地设置状态变量,则Thymeleaf将始终为您创建⼀个默认的迭代变量,该状态迭代变量名称为:迭代变量+“Stat”。(本例中则是prodStat)

1.3 条件判断

Thymeleaf使用th:if语法来做条件判断。当表达式满⾜某个条件,才将⼀个模板⽚段显示在结果中。示例: view th:if属性不仅只以布尔值作为判断条件,它将按照这些规则判定指定的表达式值为true:
  • 如果表达式的值不为null:
  • 如果值为布尔值,则为true。
  • 如果值是数字,并且不为零
  • 如果值是⼀个字符且不为零
  • 如果value是String,⽽不是“false”,“off”或“no”
  • 如果值不是布尔值,数字,字符或字符串。
th:if还有⼀个反向属性,th:unless,我们可以在前⾯的例⼦中使⽤: view (2)switch语法
示例:

User is an administrator

User is a manager

请注意,只要第⼀个th:case的值为true,则同⼀个switch语句中的其他th:case属性将被视为false。switch语句的default选项指定为th:case =“*”:

User is an administrator

User is a manager

User is some other thing

1.4模板布局语法

(1)声明模板片段及引用
在我们的模板中,我们经常希望从其他模板中包含⼀些部分,如⻚脚,⻚眉,菜单等部分。Thymeleaf使⽤th:fragment属性来定义被包含的模版⽚段,以供其他模版引用。我们在一个名为footer.html模板页加入下面这段代码:
© 2011 The Good Thymes Virtual Grocery
这段代码声明了一个名为copy的片段,我们可以使⽤th:insert或th:replace属性(以及th:include,尽管Thymeleaf 3.0不再推荐使⽤它),容易地包含在我们的主⻚中:
或者:
〜{…}称为片段表达式,它是可选的(上面第二种写法)。
片段表达式语法:
  • “〜{templatename :: selector}”:templatename是模板名(加上路径),selector是选择器,可以是片段名,也可以使用css选择器的方式说明,例如:"#id"、".class"。具体见Thymeleaf官方文档附录C。
  • “〜{templatename}” :包含名为templatename的整个模板。
  • 〜{:: selector}“或”〜{this :: selector}“ :包含在同⼀模板中的匹配指定选择器的⽚段。
⽚段可以包含任何th:*属性。 ⼀旦将⽚段包含在⽬标模板(具有th:insert /th:replace属性的模板)中,这些属性将被计算属性表达式的值,并且它们将能够引⽤此⽬标模板中定义的任何上下⽂变量th:insert和th:replace(th:include)之间的区别
  • th:insert是最简单的:它将简单地插⼊指定宿主标签的标签体中。
  • th:replace实际上⽤指定的⽚段替换其宿主标签。
  • th:include类似于th:insert,⽽不是插⼊⽚段,它只插⼊此⽚段的内容。
    示例:
copy片段:
© 2011 The Good Thymes Virtual Grocery
结果:
© 2011 The Good Thymes Virtual Grocery
© 2011 The Good Thymes Virtual Grocery
© 2011 The Good Thymes Virtual Grocery
(2)片段参数
Thymeleaf支持在定义片段名的时候给他加上参数,相当于函数的形参。在使用th:insert和th:replace(th:include)时,给参数赋值,相当于实参。

...

...
...
即使⽚段没有定义参数:

...

我们也可以使用第二种语法(必须这种)来调用:
那么我们在片段中(即使不在同一个模板中)也同样可以使用${onevar}和${twovar}的方式调用这两个变量。等价于th:replace和th:with的组合:
th:with是声明变量用的。 (3)删除模板片段
Thymeleaf使用th:remove语法来做删除模板中不需要的片段。假设我们在做模板时需要加上一些模拟数据,方便在静态页面展示时用,而当正式使用模板引擎生成页面时不需要这些模拟数据时,就可以使用th:remove语法来删除这些模拟的模板片段。示例: Mild Cinnamon 1.99 yes 3 comment/s view 当生成动态页面时,这段代码就会被删除。
th:remove参数:
  • all:删除包含标签及其所有⼦项。
  • body:不要删除包含的标签,但删除所有的⼦项。
  • tag:删除包含的标签,但不要删除其⼦项。
  • all-but-first:删除除第⼀个包含标签之外的所有⼦代。
  • none:什么都不做。 该值对于动态计算是有⽤的。
th:remove将null视为none

1.5 局部变量

Thymeleaf中的局部变量是指定义在模版⽚段中的变量,并且该变量的作⽤域为所在的模版⽚段。示例: ... prod 迭代变量就是⼀个局部变量,仅在标签的范围内可⽤。
  • 它可⽤于在该标签中执⾏的优先级低于th:each的任何其他th:*属性(这意味着它们将在th:each之后执⾏)。
  • 它可⽤于标签的任何⼦元素,例如任何元素。
Thymeleaf提供了⼀种声明局部变量的⽅式,就是th:with,相当于jsp中的c:set。示例:

The name of the first person is Julius Caesar.

当th:with被处理时,firstPer变量被创建为局部变量并被添加到来⾃上下⽂map中,以便它可以与上下⽂中声明的任何其他变量⼀起使⽤,但只能在包含在
标签内使⽤。

1.6 属性的优先级

当在同⼀个标签中写⼊多于⼀个的th:*属性时,Thymeleaf会按照属性定义的数字优先级来解析属性。优先级列表如下: Order Feature Attributes 1 Fragment inclusion 片段包含 th:insert th:replace 2 Fragment iteration 循环迭代 th:each 3 Conditional evaluation 条件判断 th:if th:unless th:switch th:case 4 Local variable definition 局部变量定义 th:object th:with 5 General attribute modification 属性修改 th:attr th:attrprepend th:attrappend 6 Specific attribute modification 指定属性修改 th:value th:href th:src … 7 Text (tag bodymodification) 修改标签体内容 th:text(转义特殊字符) th:utext(不转义特殊字符) 8 Fragment specification 声明片段 th:fragment 9 Fragment removal 删除片段 th:remove

1.7内联

(1)内联表达式
有时候我们需要把表达式写在HTML文本中,而不是标签体内。Thymeleaf提供[[…]]或[(…)]的写法来实现,[[…]]相当于t:text会转义特殊字符 、[(…)]相当于t:utext不会转义特殊字符。示例:

[[${msg}]]

[(${msg})]

假设msg =’

你好!

’,那么[[…]]在页面上就是显示的“

你好!

“,[(…)]则是一个大标题显示的”你好!“。
禁用内联:th:inline =“none”。当我们需要输出[[…]]或[(…)]序列⽽不将其内容作为表达式处理的情况时。

A double array looks like this: [[1, 2, 3], [4, 5]]!

A double array looks like this: [[1, 2, 3], [4, 5]]!

(2)内联JavaScript和css
示例:

2、表达式语法

  • 简单表达式:
    • 变量表达式:$ {…}
    • 选择变量表达式:* {…}
    • 消息表达式:#{…}
    • 链接⽹址表达式:@ {…}
    • ⽚段表达式:〜{…}
  • 字面量
    • 文本 :‘one text’ , ‘Another one!’
    • 数字字⾯值:0,34,3.0,12.3,…
    • 布尔⽂字:true,false
    • null
    • ⽂字Token:one,sometext,main,…
  • ⽂本操作
    • 字符串连接:+
    • ⽂本替换:|The name is ${name}|
  • 算术运算符
    • ⼆进制运算符:+,-,*,/,%
    • 负号(⼀元运算符):-
  • 布尔运算符
    • ⼆进制运算符:and 、or
    • 布尔否定(⼀元运算符):!,not
  • ⽐较和相等运算符:
    • ⽐较运算符:>,<,> =,<=(gt,lt,ge,le)
    • 相等运算符:==,!=(eq,ne)
  • 条件运算符:
    • If-then:(if) ? (then)
    • If-then-else:(if) ? (then) : (else)
    • Default:(value) ?: (defaultvalue)
  • 特殊符号:
    • 哑操作符:_
      示例:
'User is of type ' + (${user.isAdmin()} ? 'Administrator': (${user.type} ?: 'Unknown'))

2.1 消息表达式#{…}

Thymeleaf使用#{…}作为消息表达式,所谓消息其实就是从配置文件中取出的变量。一般用来做国际化功能。示例:

Welcome to our grocery store!

home.welcome是在配置文件中配置的。

2.2变量表达式${}

$ {…}表达式实际上是在上下⽂中包含的变量的映射上执⾏的OGNL(Object-Graph Navigation Language)对象。
示例: 对象: ${person.father.name} ${person['father']['name']} map: ${countriesByCode.ES} ${personsByName['Stephen Zucchini'].age} 数组/list: ${personsArray[0].name} 调用对象的方法: ${person.createCompleteName()} ${person.createCompleteNameWithSeparator('-')} 内置基本表达式对象:
从#符号开始:
  • #ctx:上下⽂对象。
  • #vars:上下⽂变量。
  • #locale:上下⽂区域设置。
  • #request :(仅在Web Contexts中)HttpServletRequest对象。
  • #response:(仅在Web上下⽂中)HttpServletResponse对象。
  • #session :(仅在Web上下⽂中)HttpSession对象。
  • #servletContext :(仅在Web上下⽂中)ServletContext对象。
示例: 获取国家信息: US 具体调用可以参照官方文档附录A。 工具表达式对象:
Thymeleaf将为我们提供⼀组⼯具对象:
  • #execInfo:有关正在处理的模板的信息。
  • #messages:⽤于在变量表达式中获取外部化消息的⽅法,与使⽤#{…}语法获得的⽅式相同。
  • #uris:转义URL / URI部分的⽅法
  • #conversions:执⾏配置的转换服务(如果有的话)的⽅法。
  • #dates:java.util.Date对象的⽅法:格式化,组件提取等
  • #calendars:类似于#dates,但对于java.util.Calendar对象。
  • #numbers:⽤于格式化数字对象的⽅法。
  • #strings:String对象的⽅法:contains,startsWith,prepending/appending等
  • #objects:⼀般对象的⽅法。
  • #bools:布尔评估的⽅法。
  • #arrays:数组的⽅法。
  • #lists:列表的⽅法。
  • #sets:集合的⽅法。
  • #maps:地图⽅法。
  • #aggregates:在数组或集合上创建聚合的⽅法。
  • #ids:处理可能重复的id属性的⽅法(例如,作为迭代的结果)。
具体调用参考官方文档附录B 2.3 选择表达式*{}
*{}和${}基本相同,只有一个区别:星号语法计算所选对象⽽不是整个上下⽂的表达式。 也就是说,只要没有选定的对象,$和*语法就会完全相同。示例:

Name: Sebastian.

Surname: Pepper.

Nationality: Saturn.

等价于:

Name: Sebastian.

Surname: Pepper.

Nationality: Saturn.

或者:

Name: Sebastian.

如果没有执⾏对象选择,则$和星号语法是等效的。

2.4 URL链接表达式@{}

示例: view view view 注意:
  • 如果需要⼏个参数,这些参数将以逗号分隔:@ {/ order /process(execId = $ {execId},execType =‘FAST’)}
  • 以/开头的相对URL(例如:/ order / details)将⾃动以应⽤程序上下⽂名称为前缀。
  • URL路径中也允许使⽤变量模板:@ {/ order / {orderId} /details(orderId = $ {orderId})}

2.5 片段引用表达式~{}

示例:
...

2.6 字面量

(1)纯⽂本
⽂本⽂字只是包含在单引号之间的字符串。 它们可以包含任何字符,但是应该使⽤’转义其中的任何单引号。

Now you are looking at a template file.

(2)数字

The year is 1492.

In two years, it will be 1494.

(3)布尔
布尔字⾯量包含true和false。
== false被写在⼤括号之外,所以它是Thymeleaf来处理的。如果它是写在⼤括号内,那将是OGNL / SpringEL引擎的责任。
(4)NULL
(5)⽂本符号
和纯文本类似,但是没有单引号引起来。只允许使⽤字⺟(A-Z和a-z),数字(0-9),括号([和]),点(.),连字符( - ) 和下划线(_)。 所以没有空⽩,没有逗号等。
...

2.7 文本操作

(1)追加⽂本 (2)文本替换
⽂本替换允许容易地格式化包含变量值的字符串,⽽不需要使⽤“…”+“…”附加⽂字。 等价与: 只有变量/消息表达式($ {…},* {…},#{…})才允许包含在|…|中来实现⽂本替换。 其他情况则不允许,如⽂本(’…’),布尔/数字令牌,条件表达式等。

2.8 算术运算符

Thyme Leaf标准表达式还⽀持⼀些算术运算:+, - ,*,/和%
请注意,这些运算符也可以在OGNL变量表达式本身中应⽤(在这种情况下将由OGNL解析执⾏,⽽不是Thymeleaf标准表达式引擎来解析执⾏。
其中⼀些运算符存在⽂本别名:div(/),mod(%)

2.9 比较和等值运算符

表达式中的值可以与>,<,> =和<=符号进⾏⽐较,并且可以使⽤==和!=运算符来检查是否相等(或缺少)。 请注意,XML类型的模版中不应在属性值中使⽤<和>符号,应该使⽤&lt; 和&gt;。
⼀个更简单的替代⽅案是使⽤这些运算符的⽂本别名:gt(>),lt(<),ge(> =),le(<=),⾮(!)。 还有eq(==),neq /ne(!=)。

2.10 条件表达式

... 条件表达式(condition,then和else)的三个部分都有⾃⼰的表达式,这意味着它们可以是变量($ {…},* {…}),消息(#{…}) ,URL(@{…})或⽂字(’…’)。
条件表达式也可以使⽤括号嵌套: ... Else表达式也可以省略,在这种情况下,如果条件为false,则返回null值: ... `在这里插入代码片`

2.11 默认表达式

默认表达式是⼀种特殊类型的条件值,没有then那个部分。允许您指定两个表达式:如果计算结果不为null,则使⽤第⼀个表达式,但如果计算结果为null则使⽤第⼆个表达式。
...

Age: 27.

age不为null,则是age的值,否则就是no age specified。
可以在括号之间包含嵌套表达式:

Name: Sebastian

2.12 哑操作符号

哑操作符号由下划线符号(_)表示。这个标记指定表达式不处理任何结果,即相当于可执⾏的属性(例如:⽂
本)不存在⼀样。 no user authenticated