Marco's Java【SpringBoot入门(六) 之 Thymeleaf模板引擎的使用】

前言

本节呢给大家介绍一个新鲜 “玩意儿” 叫做Thymeleaf,Thymeleaf翻译过来就是 “百里香叶” 的意思
在这里插入图片描述
我发现这些大佬儿特别喜欢用叶子作为标识啊,不过我个人还是挺喜欢这绿叶子 (不是绿帽子!)。说了半天这东西是干啥的呢?客官们接着往下看~

什么是Thymeleaf模板

简单来说,Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP,实现网页的 “动态化” ,相较与其他的几个模板引擎,它有如下三个吸引人的特点:

1)Thymeleaf在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。

2)Thymeleaf 开箱即用的特性。它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、
OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。

3)Thymeleaf 提供spring标准方言和一个与 SpringMVC完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。

总而言之在今后的开发中我们也不会再使用jsp,转而使用Thymeleaf模板替代它,毕竟它是为Spring “量身定做” 的。


Thymeleaf的相关语法

1,简单表达式
  1、变量的表达式:${…}
  2、选择变量表达式:*{…}
  3、信息表达式:#{…}
  4、链接URL表达式:@{…}
2,字面值 th:text
  1、文本文字:‘one text’, ‘Another one!’,…
  2、文字数量:0, 34, 3.0, 12.3,…
  3、布尔型常量:true, false
  4、空的文字:null
  5、文字标记:one, sometext, main,…  
3,文本处理
  1、字符串并置:+
  2、文字替换:|The name is ${name}|  
4,表达式基本对象
  1、#ctx:上下文对象
  2、#vars:上下文变量
  3、#locale:上下文语言环境
  4、#httpServletRequest:(只有在Web上下文)HttpServletRequest对象
  5、#httpSession:(只有在Web上下文)HttpSession对象。
5,实用工具对象 
  1、#dates: java.util的实用方法。对象:日期格式、组件提取等.
  2、#calendars:类似于#日期,但对于java.util。日历对象
  3、#numbers:格式化数字对象的实用方法。
  4、#strings:字符串对象的实用方法:包含startsWith,将/附加等。
  5、#objects:实用方法的对象。
  6、#bools:布尔评价的实用方法。
  7、#arrays:数组的实用方法。
  8、#lists:list集合。
  9、#sets:set集合。
  10、#maps:map集合。
  11、#aggregates:实用程序方法用于创建聚集在数组或集合.
  12、#messages:实用程序方法获取外部信息内部变量表达式,以同样的方式,因为它们将获得使用# {…}语法
  13、#ids:实用程序方法来处理可能重复的id属性(例如,由于迭代)。


SpringBoot项目Thymeleaf模板页面存放位置

之前我们的jsp页面都是存放在webapps中的/WEB-INF/view中,避免外部请求直接通过.jsp的方式访问到这个页面,那么Thymeleaf页面也应该有自己的储存的位置对吧?为了找到答案,我们来看看它的源码,看看能否找到些线索。咱们先找到Thymeleaf模板在SpringBoot中存放的位子,瞅瞅它里面的结构。
在这里插入图片描述
发现Thymeleaf包中有三个类,我们选择打开第一个自动配置的类来看看
在这里插入图片描述
根据之前的经验,我们可以初步的分析出ThymeleafAutoConfiguration是依赖TemplateMode.class, SpringTemplateEngine.class这两个类的,另外@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })这个注解之前没有讲过,我来提一下,它的意思就是当前类需要等待被{ }包裹的类加载完之后才能被加载。
在这里插入图片描述
那好奇心又勾起了我,到底是什么类这么牛,这么有面子还需要先加载?
说时迟那时快,我点开WebMvcAutoConfiguration,发现这不正是我们之前分析SpringBoot不需要任何配置就能启动的 “灵魂之源” WebMvc自动装配器么?好吧,打扰了,确实Thymeleaf必须要等配置齐全了才能运行…
在这里插入图片描述
好,不能再跑偏了,别忘了我们还身负重任!仔细想想,要找到存放你的 “窝” ,那肯定是放在配置文件中写死了的,找找看有没有啥和配置文件搭边的。按照刚才的推想,找到一个properties文件?

private final ThymeleafProperties properties;

点开看看里面有没有我们想要的东西。
在这里插入图片描述
果然!找到了Thymeleaf的老窝,根据上面的信息不难推断,存放Thymeleaf的地方就是classpath下的templates文件夹,并且他还默认的给我们后面加上了.html后缀,这和我们之前的视图解析器的用法是不是很类似?
通过这种方式,我们想要再控制器中实现页面的跳转,直接使用 return index(html页面的名字)的方式就行啦~
当然有的朋友想说,我已经习惯了之前存放jsp页面的位置,我念旧,不想变动,咋办?
施主既然有要求,贫道自然会帮你解决… 难不倒我的。既然我都知道了Thymeleaf内部是啥结构,我就可以改变它!解决以上问题的办法就是创建一个application.yml,并完成下方的配置就可以了。
在这里插入图片描述


好啦,今日的开胃菜已经够多了,该上 “主食” 了,不然撑不下去的。

在创建项目之前呢,大家先安装一下Thymeleaf代码提示功能,直接在在Eclipse中安装Thymeleaf插件即可。
插件的地址为:thymeleaf插件下载地址
安装方式参考博文(PS:太懒了…不想写…) https://blog.csdn.net/king_kgh/article/details/76084398

创建项目

插件下载完成之后,咱们先创建一个SpringBoot项目,我会带着大家看看如何使用Thymeleaf,比看概念强一万倍!
在这里插入图片描述
注意了,在Avalilable这里搜索thyme,勾选之后,SpringBoot会帮我们导入thyme的包
在这里插入图片描述
其实SpringBoot中默认的配置了thymeleaf,只不过被<dependencyManagement></dependencyManagement>包裹起来了,因此当我们需要的时候,直接配置,不用填写版本号。
在这里插入图片描述

Thymeleaf读取xxx.propertis里面的对象

第一步:引入layui
在这里插入图片描述
第二步:创建common.properties
在src/main/resources目录下创建common.properties作为数据源
在这里插入图片描述
第三步:创建showStudent.html
引入<html xmlns:th="http://www.thymeleaf.org">标签之后,会出现如下的自动提示
在这里插入图片描述
这需要注意css和javascript导入资源文件标签是不一样的,css使用的是th:href,javascript使用的是th:src

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="#{common.title}">Insert title here</title>
<link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all">
<script th:src="@{/layui/layui.js}" charset="utf-8"></script>
</head>
<body>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
  <legend th:text="#{student.title}"></legend>
</fieldset>   
<div style="padding: 20px; background-color: #F2F2F2;">
  <div class="layui-row layui-col-space15">
    <div class="layui-col-md6">
      <div class="layui-card">
      	<div class="layui-card-body" th:text="#{student.id}">学生编号</div>
        <div class="layui-card-body" th:text="#{student.name}">学生姓名</div>
        <div class="layui-card-body" th:text="#{student.sex}">学生性别</div>
        <div class="layui-card-body" th:text="#{student.address}">学生地址</div>
        <div class="layui-card-body" th:text="#{student.phone}">学生电话</div>
        <div class="layui-card-body" th:text="#{student.age}">学生年龄</div>
        <div class="layui-card-body" th:text="#{student.birth}">学生日期</div>
      </div>
    </div>
  </div>
</div> 
</body>
</html>

第四步:创建IndexController

package com.marco.controller;

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

@Controller
@RequestMapping("index")
public class IndexController {
		
	/**
	 * 跳转到template文件夹下的index.html
	 * @return
	 */
	@RequestMapping("goToIndex")
	public  String goToIndex() {
		return "index"; 
	}
	
	/**
	 * 跳转到template文件夹下的showStudent.html
	 * @return
	 */
	@RequestMapping("showStudent")
	public String showStudent() {
		return "showStudent";
	}
}

第五步:测试
弄了半天,数据都 “乱码” 了?是不是编码没设置好啊?
在这里插入图片描述
其实数据 “乱码” 原因本质上是值没有取到,因为common.properties没有被加载。那怎么去加载我们的配置文件呢?解决上面的问题,需要创建咱们配置一下,我这里就命名为I18NConfig。

I18N (其来源是英文单词internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称。在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改变就能够适应不同的语言和地区的需要。对程序来说,在不修改内部代码的情况下,能根据不同语言及地区显示相应的界面。
在全球化的时代,国际化尤为重要,因为产品的潜在用户可能来自世界的各个角落。通常与i18n相关的还有L10n(“本地化”的简称)。

解决common.properties的数据获取不到的问题

这里需要提到的一点,关于方法messageSource.setBasename("common")

package com.marco.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;

@Configuration
public class I18NConfig {
	
	public ResourceBundleMessageSource messageSource() {
		ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
		messageSource.setUseCodeAsDefaultMessage(true);
		messageSource.setFallbackToSystemLocale(false);
		
		messageSource.setBasename("common");//需要被读取的文件的名字,.properties缺省
		messageSource.setDefaultEncoding("UTF-8");//设置默认的字符编码
		
		messageSource.setCacheSeconds(2);//以秒为单位
		return messageSource;
	}
}

添加了I18NConfig之后我们再来看看效果吧
在这里插入图片描述
数据获取到了,没有问题!不过还没结束,我们接着创建另外一个配置文件common_zh_CN.properties,并且在里边用中文将我们刚才的内容翻译并替换掉

第六步:创建common_zh_CN.properties
在这里插入图片描述
什么鬼?我打的是中文啊… 这是因为,在SpringBoot中创建的properties文件,只要输入中文都会自动的转成unicode编码格式。如果想正常的使用中文,需要定义为yml文件。

第七步:测试
欸?我们发现在两个properties文件同时存在的情况下,SpringBoot 默认会先解析common_zh_CN.properties文件,这是为什么呢?
在这里插入图片描述
因为此时的操作系统的语言环境为中文 所以读取的是common_zh_CN.properties里面的内容,如果是英文环境,则默认会取读取的是common_en_US.properties的内容,原因是SpringBoot默认支持国际化信息,也就是当我们访问一个网站切换中英界面时,会推送出不同的页面。
在这里插入图片描述
SpringBoot能支持国际化信息,本质上是内置了区域解析器,我们点开defaultLocale就可以发现里面定义了很多国家的语言,因此当他读取配置文件的时候也会默认先去读取这些包含国际化信息的properties文件
在这里插入图片描述


Thymeleaf读取Model里面的对象

上面我们使用的是固定的文本格式获取数据,这种方式使用的并不多,接着我们来看看怎么获取Servlet作用域中的值吧~

第一步:创建Student
在这里插入图片描述
第二步:修改IndexController
在之前的IndexController中添加下面的方法,我们一共添加6条数据,并使用Model容器装配数据

/**
 * 跳转到template文件夹下的showStudent.html
 * @return
 */
@RequestMapping("showAllStudent")
public String showAllStudent(Model model) {
	List<Student> students = new ArrayList<>();
	for (int i = 1; i <= 6; i++) {
		Student student = new Student(i, "marco" + i, 18 + i, 
			i%2 == 0 ? "男" : "女", "13595623654" + i, "武汉" + i, new Date());
		students.add(student);
	}
	model.addAttribute("students", students);
	return "showAllStudent";
}	

第三步:创建showAllStudent.html
之前我们在jsp中可以通过jstl的foreach标签来循环获取多条数据,那么在Thymeleaf中当然也会有类似的方法,我们先来找找看,发现有个和foreach还比较类似的标签,那决定就是你了!
在这里插入图片描述

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="#{common.title}">Insert title here</title>
<link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all">
<script th:src="@{/layui/layui.js}" charset="utf-8"></script>
</head>
<body>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
  <legend th:text="#{student.title}"></legend>
</fieldset>   
<div style="padding: 20px; background-color: #F2F2F2;">
  <div class="layui-row layui-col-space15">
    <div class="layui-col-md4" th:each="student:${students}">
      <div class="layui-card">
      	<div class="layui-card-body" th:text="${student.id}">学生编号</div>
        <div class="layui-card-body" th:text="${student.name}">学生姓名</div>
        <div class="layui-card-body" th:text="${student.sex}">学生性别</div>
        <div class="layui-card-body" th:text="${student.address}">学生地址</div>
        <div class="layui-card-body" th:text="${student.phone}">学生电话</div>
        <div class="layui-card-body" th:text="${student.age}">学生年龄</div>
        <div class="layui-card-body" th:text="${#dates.format(student.birth,'yyyy:MM:dd HH:mm:ss')}">学生日期</div>
      </div>
    </div>
  </div>
</div> 
</body>
</html>

不知道大家发现没有,当我们获取文本的数据的时候,使用得是#{common.title}这种方式,使用链接得时候使用的是th:src="@{/layui/layui.js}"这种方式,获取作用域对象得属性值时又换了种方式th:text="${student.address}",是不是觉得很麻烦?但是仔细想想,这里边也有规律可以寻,比如说我们之前使用xxxMapper.xml的时候,想获取值就是通过#{ },而xml刚好是文本,获取的是文本值,之前在jsp页面种也是通过${ }的方式获取值,因此,这个也比较好记啦,剩下的链接@{ }你可以把它想象成email的格式,email的信息本身也相当于链接(邮箱的链接),这样去记,就不会混淆啦~

第四步:测试
在这里插入图片描述


Themeleaf在js中取值

大家回忆一下,之前呢我们在js种怎么取到request作用域种的值的。是不是下面这种方式?
在这里插入图片描述
那么我们来测试下看看在Thymeleaf中,这样是否行得通,这样我们修改下后台的IndexController,因为之前后台传过来的是一个List,我们这样取值肯定会出事的,所以我们来添加一个showOneStudent()的方法。

/**
 * 跳转到template文件夹下的showOneStudent.html
 * @return
 */
@RequestMapping("showOneStudent")
public String showOneStudent(Model model) {
	Student student = new Student(1, "marco", 18, "男", "13652145236", "武汉", new Date());
	model.addAttribute("student", student);
	return "showOneStudent";
}

前台把th:each中的内容去掉就好啦,我就不重复上代码了。创建好之后我们来测试一下。

咦额… 好像报错了,那证明我们的想法是错的,jsp中的那一套在Thymeleaf里还是不顶用啊,那该怎么做呢?
在这里插入图片描述
这才是正确的打开方式… 这个中括号感觉很熟悉对不?
在这里插入图片描述
在这里插入图片描述
我们之前在layui中的表格的cols标签有使用过类似的方式
在这里插入图片描述
Mapper.xml中的<![CDATE[]]>标签也是有两个中阔号包裹,所以说[[]]这种方式并不是Thymeleaf独创的,使用的时候一定要避免冲突,特别是和layui结合使用的时候,稍微提一下,如果在使用Thymeleaf时也是用到了layui,那么layui的中的cols标签的[[]]之间要加上空格,例如[ [] ]

我们这里再稍微拓展一下如何访问带参数的消息

访问带参数的消息

我们在之前的common.properties文件中加上common.welcome=welcome {0} to China {1}
在这里插入图片描述
接着咱们在页面上添加标签<legend th:text="#{common.welcome}"></legend>来看看效果
在这里插入图片描述
好像没啥特别的啊?不急,我们接着修改刚加进去的页面标签

<legend th:text="#{common.welcome('marco','~')}"></legend>

很神奇对吧!不过这种方式用的不是特别多,玩玩就好啦~
在这里插入图片描述


Thymeleaf链接传值

Thymeleaf为我们提供了一种特殊的url传值方式,称之为链接传值,大家可以看到下面的第一种方式是我们的普通传值方式,第二种就是Thymeleaf的链接传值方式了(利用 th:href 标签)。
在这里插入图片描述
老样子,还是来测试一下是否可以获取到()中的值,点击登录按钮
在这里插入图片描述
页面报错了咱不管,不过值是顺利的获取到了!
在这里插入图片描述


ThymeleafObjects的使用

ThymeleafObjects指的就是作用域中的值,学习过Servlet的朋友肯定对request、session、application等名词不会陌生,之前学习jsp的时候,我们就是从这几个作用域中获取值,从而做出一个个动态的页面,jsp能做出动态的页面本质是因为jsp就是一个Servlet,但是本节我们学习的Thymeleaf其实就是一个html页面,只不过是一个比较 “特殊” 的html页面,特殊就特殊在使用它也能够做出动态页面的效果,jsp能做的事它也能做到,比如说从Servlet作用域中获取值!

我们还是拿案例说事儿,咱们在IndexController中事先准备一个方法,存点儿东西到上面提到的三个作用域里

/**
 * 跳转到template文件夹下的showObject.html
 * @return
 */
@RequestMapping("showObject")
public String showObject(Model model, HttpServletRequest request) {
	request.setAttribute("msg", "i'm request");
	request.getSession().setAttribute("msg", "i'm session");
	request.getServletContext().setAttribute("msg", "i'm context");
	return "showObject";
}

然后准备一个小巧的页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="#{common.title}">Insert title here</title>
<link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all">
<script th:src="@{/layui/layui.js}" charset="utf-8"></script>
</head>
<body>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
</fieldset>   
<div style="padding: 20px; background-color: #F2F2F2;">
  <div class="layui-row layui-col-space15">
    <div class="layui-col-md4">
      <div class="layui-card">
      	<!-- 从request作用域中取值 -->
      	Request:<div class="layui-card-body" th:text="${msg}"></div>
      	<!-- 从session作用域中取值 -->
        Session:<div class="layui-card-body" th:text="${session.msg}"></div>
      	<!-- 从application(context)作用域中取值 -->
        Context:<div class="layui-card-body" th:text="${application.msg}"></div>
      </div>
    </div>
  </div>
</div> 
</body>
</html>

是不是很简单?其实和jsp获取值的方式是差不多的,比如说之前jsp页面从session中取值是使用${sessionScope.attribute},而在Thymeleaf中使用的是${session.attribute},写起来更简单了!
我们还是来看看页面上的效果吧~
在这里插入图片描述

后语

到此为止,咱们的Thymeleaf就介绍完啦,其实使用方式和jsp没有特别大的区别,只不过Thymeleaf的功能似乎划分的更细,更强大,因此合理的运用这 “百里香叶” 是非常有必要的,多练习吧~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值