一、概述Thymeleaf
Spring Boot可整合的模板引擎技术:1. FreeMarker 2. Groovy 3. Thymeleaf 4. Mustach
1、什么是Thymeleaf
Thymeleaf是一种现代的基于服务器端的java模板引擎技术,也是一个优秀的面向java的xml、xhtml、html5页面模板,它具有丰富的标签语言、函数和表达式,在使用springboot框架进行页面设计时,一般会选择Thymeleaf模版。
2、优点
① 界面设计人员和程序设计人员可以共享同一套页面
比如下面一段含有Thymeleaf语句的HTML代码:
<p th:text="#{hello}">欢迎进入Thymeleaf的学习</p>
界面设计人员将看到(静态展示):欢迎进入Thymeleaf的学习
程序设计人员将看到(动态展示):如果变量hello的值为“hello world!”,那么展示为hello world!
从结果看,只是内容的变化,样式不变,所以可以共享同一套页面
3、处理模板模式
①HTML
不严格要求html标签完整,比如:<input ......>,结尾缺少“/”没事。
②XML
要求XML格式完整,但不检查内容是否符合某种规范,比如dtd
③TEXT
④JAVASCRIPT
⑤RAW:原型,不处理模板
4、模板引擎的作用
TemplateEngine将含有逻辑的代码转换成纯输出,看下面的案例去理解
二、Thymeleaf能实现什么功能
创建Springboot项目,在pom.xml中添加如下坐标(即引入Thymeleaf依赖)
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
</dependency>
1、处理html
①创建测试类ThymeleafTest
public class ThymeleafTest {
@Test
public void testHtml() {
TemplateEngine templateEngine = new TemplateEngine();
Context ctx = new Context();
ctx.setVariable("hello", "hello world");
String result = templateEngine.process(
"<p th:text='${hello}'> 欢迎进入Thymeleaf的学习 </p>",
ctx);
System.out.println(result);
}
}
②输出如下:
<p>hello world</p>
结论:TemplateEngine能把含有逻辑的代码转换成纯html输出。
2、更换模板解析器,处理xml
默认模板处理模式是html,通过更换模板解析器,处理其他格式的模板,例如xml
@Test
public void testXML() {
TemplateEngine templateEngine = new TemplateEngine();
// 新建模板解析器
StringTemplateResolver resolver = new StringTemplateResolver();
// 设置模板模式为XML
resolver.setTemplateMode(TemplateMode.XML);
// 将解析器设置到引擎实例中
templateEngine.setTemplateResolver(resolver);
Context ctx = new Context();
// 处理一段含有Thymeleaf逻辑的XML语句
String result = templateEngine.process(
"<bean id=\"myBean\" th:attr='class=org.crazyi.Test'></bean>",
ctx);
System.out.println(result);
}
输出结果:<bean id="myBean" class="org.crazyi.Test"></bean>
3、处理资源文件(例如:xx.html)
①在resources下创建index.html
<input type="text" th:value="angus"/>
②创建测试方法
@Test
public void testClassLoader() {
TemplateEngine templateEngine = new TemplateEngine();
// 创建解析器
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
// 设置到模板引擎中
templateEngine.setTemplateResolver(resolver);
// 处理classpath下的 index.html文件
String result = templateEngine.process("index.html", new Context());
System.out.println(result);
}
输出:<input type="text" value="angus"/>
4、处理变量(这里变量名为data)
①创建资源文件var.html
<input type="text" th:value="${data.name}"/>
②创建DataObject类,存放数据
public class DataObject {
private String name;
public DataObject(String name) {
super();
this.name = name;
}
public DataObject() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
③创建测试方法
@Test
public void testVar() {
TemplateEngine templateEngine = new TemplateEngine();
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
templateEngine.setTemplateResolver(resolver);
// 设置参数到Context中
Context ctx = new Context();
ctx.setVariable("data", new DataObject("angus"));
String result = templateEngine.process("var.html", ctx);
System.out.println(result);
}
输出:<input type="text" value="angus"/>
5、遍历集合
①创建资源文件iteration.html
<table>
<tr th:each="data : ${datas}">
<td th:text="${data.name}">Angus</td>
</tr>
</table>
②创建测试方法
@Test
public void testIteration() {
TemplateEngine templateEngine = new TemplateEngine();
// 创建解析器
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
// 设置到模板引擎中
templateEngine.setTemplateResolver(resolver);
// 设置集合数据
List<DataObject> datas = new ArrayList<DataObject>();
datas.add(new DataObject("a"));
datas.add(new DataObject("b"));
Context ctx = new Context();
ctx.setVariable("datas", datas);
// 处理classpath下的 index.html文件
String result = templateEngine.process("iteration.html", ctx);
System.out.println(result);
}
输出:
<table>
<tr>
<td>a</td>
</tr>
<tr>
<td>b</td>
</tr>
</table>
6、设置前缀和后缀
①在resources下创建templates文件夹,并创建index.html
<span th:text="hello"></span>
②创建测试方法
@Test
public void testFix() {
TemplateEngine templateEngine = new TemplateEngine();
// 设置前缀与后缀
ClassLoaderTemplateResolver resolover = new ClassLoaderTemplateResolver();
resolover.setPrefix("/templates/");
resolover.setSuffix(".html");
templateEngine.setTemplateResolver(resolover);
// 处理 /templates/index.html,前缀+模板名称+后缀
String result = templateEngine.process("index", new Context());
System.out.println(result);
}
输出:<span>hello</span>
三、Thymeleaf基本语法
1、常用标签
示例:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" media="all"
href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
<title>Title</title>
</head>
<body>
<p th:text="#{hello}">欢迎进入Thymeleaf的学习</p>
</body>
</html>
2、标准表达式
说明 | 表达式语法 |
变量表达式 获取上下文中的变量值 | ${...} |
选择变量表达式 用于从被选定对象获取属性值 | *{...} |
消息表达式 用于Thymeleaf模板页面国际化内容的动态替换和展示 | #{...} |
链接URL表达式 用于页面跳转或者资源的引入 | @{...} |
片段表达式 用来标记一个片段模板,并根据需要移动或传递给其他模板 | ~{...} |
3、Thymeleaf内置对象
Thymeleaf为变量所在域提供了一些内置对象,如下
- #ctx:上下文对象
- #vars:上下文变量
- #locale:上下文区域设置
- #request:(仅限Web Context)HttpServletRequest对象
- #response:(仅限Web Context)HttpServletResponse对象
- #session:(仅限Web Context)HttpSession对象
- #servletContext:(仅限Web Context)ServletContext对象
四、Spring Boot 中的静态资源的访问路径
1、Spring Boot默认将/**所有访问映射到以下目录:
- classpath:/META-INF/resources/:项目类路径下的META-INF文件夹下 的resources文件夹下的所有文件。
- classpath:/public/:项目类路径下的public文件夹下的所有文件。
- classpath:/resources/:项目类路径下的resources文件夹下的所有文件。
- classpath:/static/:项目类路径下的static文件夹下的所有文件。
Springboot默认依次从classpath:/META-INF/resources 、classpath:/resources/ 、classpath:/static/ 、classpath:/public/里面查找静态资源。
这个查找顺序可以通过源码查看:WebMvcAutoConfiguration--》搜索getStaticLocations--》进入该方法--》寻着轨迹就能找到
2、修改静态资源存放位置:
spring.resources.static-locations=字符串数组
五、springboot整合Thymeleaf 完成数据的页面展示
1、创建Spring Boot项目,引入Thymeleaf依赖和Web场景依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、在全局配置文件中增加如下配置
#如设置模板缓存、模板编码、模板样式、指定模板页面存放路径、指定模板页面名称的后缀
#thymeleaf页面缓存设置(默认为true),开发中关闭缓存(false),数据改变时及时响应,上线稳定后打开缓存(true)
spring.thymeleaf.cache = false
spring.thymeleaf.encoding = UTF-8
spring.thymeleaf.mode = HTML
#默认值,模板页面存放路径
spring.thymeleaf.prefix = classpath:/templates/
#默认值,模板页面名称的后缀
spring.thymeleaf.suffix = .html
#如果下面的配置生效,那么访问路径加上项目名
#server.servlet.context-path=/my04
#拼接地址 classpath:/templates/login.html
3、创建控制类:@Controller
创建一个用于前端模板页面动态数据替换效果测试的访问实体类LoginController
注意:返回值不能是void,否则访问路径(即toLoginPage)被当成模板名称
@Controller
public class LoginController {
@GetMapping("/toLoginPage")
public String toLoginPage(Model model){
model.addAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR));
return "login";
}
}
4、创建模板页面并引入静态资源文件
项目结构图
下载静态资源文件https://download.csdn.net/download/daqi1983/89029598
创建一个用户登录的模板页面login.html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1,shrink-to-fit=no">
<title>用户登录界面</title>
<link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet">
<link th:href="@{/login/css/signin.css}" rel="stylesheet">
</head>
<!-- 在body标签中通过th:text引入了后台动态传递过来的当前年份currentYear -->
<body class="text-center">
<!-- 用户登录form表单 -->
<form class="form-signin">
<img class="mb-4" th:src="@{/login/img/login.jpg}" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal">请登录</h1>
<input type="text" class="form-control"
th:placeholder="用户名" required="" autofocus="">
<input type="password" class="form-control"
th:placeholder="密码" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 记住我
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">登录</button>
<p class="mt-5 mb-3 text-muted">© <span th:text="${currentYear}">2018</span>-<span th:text="${currentYear}+1">2019</span></p>
</form>
</body>
</html>
5、效果测试
启动项目进行测试,在浏览器上访问http://localhost:8080/toLoginPage,在页面底部动态显示了当前日期2019-2020,而不是文件中的静态数字2018-2019
六、Thymeleaf国际化页面
1、编写多语言国际化文件以及配置文件
springboot 默认识别的语言配置文件为resources下的messages.properties、messages_语言代码_国家代码.properties。
这里我们使用自定义的语言配置文件,格式:文件前缀名. properties、文件前缀名_语言代码_国家代码.properties,并放在resources下的i18n文件夹下:
login.properties、login_zh_CN.properties
login.tip=请登录
login.username=用户名
login.password=密码
login.rememberme=记住我
login.button=登录
login_en_US.properties
login.tip=Please sign in
login.username=Username
login.password=Password
login.rememberme=Remember me
login.button=Login
2、编写配置文件
由于是自定义语言配置文件,所以要配置国际化文件基础名
spring.messages.basename=i18n.login
3、定制区域信息解析器
由于我们是根据点击页面的超链接形成的请求参数手动切换语言,所以需要定制区域信息解析器。默认是根据请求头的accept-language的语言信息来选择对应的语言配置文件完成自动切换语言
建子包config,自定义区域信息解析器配置类
@Configuration
public class MyLocalResolver implements LocaleResolver {
// 自定义区域解析方式
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
// 获取页面手动切换传递的语言参数l
String l = httpServletRequest.getParameter("l");
// 获取请求头自动传递的语言参数Accept-Language
String header = httpServletRequest.getHeader("Accept-Language");
Locale locale=null;
// 如果手动切换参数不为空,就根据手动参数进行语言切换,否则默认根据请求头信息切换
if(!StringUtils.isEmpty(l)){
String[] split = l.split("_");
locale=new Locale(split[0],split[1]);
}else {
// Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
String[] splits = header.split(",");
String[] split = splits[0].split("-");
locale=new Locale(split[0],split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, @Nullable
HttpServletResponse httpServletResponse, @Nullable Locale locale) {
}
// 将自定义的MyLocalResovel类重新注册为一个类型LocaleResolver的Bean组件,能覆盖默认的解析器
@Bean
public LocaleResolver localeResolver(){
return new MyLocalResolve();
}
}
4、页面国际化使用
用户登录页面login.html结合Thymeleaf模板引擎实现国际化功能,核心代码如下
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">请登录</h1>
<input type="text" class="form-control"
th:placeholder="#{login.username}" required="" autofocus="">
<input type="password" class="form-control"
th:placeholder="#{login.password}" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me">[[#{login.rememberme}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit"
th:text="#{login.button}">登录</button>
<p class="mt-5 mb-3 text-muted">© <span th:text="${currentYear}">2018</span>
-<span th:text="${currentYear}+1">2019</span></p>
<a class="btn btn-sm" th:href="@{/toLoginPage(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/toLoginPage(l='en_US')}">English</a>
<!--[[#{login.rememberme}]]行内表达式 用于标签外部数据的展示-->
5.整合效果测试
①启动项目进行效果测试,在浏览器上访问http://localhost:8080/toLoginPage
乱码:设置属性文件的编码为utf-8
②以火狐浏览器为例,设置语言为美国英语
这时再去访问登录页面时,就变成英文显示了
③如果点击页面的English,也会以英文显示
定制应用程序错误页面
作业:
springboot整合redis和thymeleaf,在浏览器端显示张有才的信息