前言

以前我们都是使用jsp,前后端一起开发的引擎,其实是用久了之后很不好维护,后台的逻辑很多写在前端,接受非常麻烦,于是springboot出来后,推出了两套模板引擎,非常受广大程序员青睐,于是今天给大家介绍其中一种模板:thymeleaf

一、介绍

Thymeleaf是跟Velocity、FreeMarker类似的模板引擎,它可以完全替代JSP,相较与其他的模板引擎,它主要有以下几个特点:

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

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

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

二、Thymeleaf 常用的表达式、标签和函数

2.1、常用表达式

• ${...}变量表达式。
•* { .. . } 选择表达式。
• #{...}消息文字表达式。
• @ {} 链接url 表达式。
• #maps 工具对象表达式。

2.2、常用标签

• th:action 定义后台控制器路径。
• th:each 1,盾环语-句。
• th:field 表单字段绑定。
• th:href 定义超链接。
• th:id div 标签中的ID 声明,类似HTML 标签中的归属性。
• th:if 条件判断语句。
• th:include 布局标签,替换内容到引入文件。
• th :企agment 布局标签,定义一个代码片段,方便其他地方引用。
• th:object 替换对象。
• th:src 图片类地址引入。
• th:text 显示文本。
• th:value 属性赋值。

2.3、常用函数

• #dates 日期函数。
• #lists 列表函数。
• #arrays 数组函数。
• #strings 字符串函数。
• #numbers 幸生字函捷生。
• #ca lendars 日历函数。
• #objects 对象函数。
• #bools 逻辑函数。

三、整合到springboot步骤

3.1、目录示意图

image.png

3.2、依赖

compile("org.springframework.boot:spring-boot-starter-thymeleaf:$springbootStarterThymeleafVersion")

3.3、application.yml配置

# web port
server:
  port: 8097

spring:
  mvc:
    static-path-pattern: /static/**
#    static-path-pattern: /**
  resources:
    static-locations: classpath:/static/
  thymeleaf:
    #模板的模式,支持 HTML, XML TEXT JAVASCRIPT
    mode: HTML5
    #编码 可不用配置
    encoding: UTF-8
    #内容类别,可不用配置
    content-type: text/html
    #开发配置为false,避免修改模板还要重启服务器
    cache: false
    #配置模板路径,默认是templates,可以不用配置
    prefix: classpath:/templates/

3.4、编写访问类Controller

/**
 * 路径访问
 * 注意:
 * 配置里面不设置mvc.static-path-pattern: 的话并且不指定@RequestMapping("/")会默认访问static里面index文件
 * 配置里面设置mvc.static-path-pattern: /**会默认访问static里面index文件
 * 设置的话就会默认访问templates目录里面的inde文件,不需要设置@RequestMapping("/")来达到访问inde文件
 * 目录访问错误会跳到404或者500页面,ErrorInterceptor文件进行拦截
 *
 * @author qiwu
 * <br> Date : 2021/1/23 12:16 上午
 * <br> Copyright (c) 2021/1/23 ZiYun Tech.
 */
@Controller
public class HomeController {

    @RequestMapping(value = "/index")
    public String index() {
        return "index";
    }

    @RequestMapping("/hello")
    public String greeting(ModelMap modelMap){
        modelMap.addAttribute("name","其实我是个新手");
        modelMap.addAttribute("host","https://www.baidu.com");
        return "hello";
    }

}

3.5、拦截器(一般项目中必不可少,当然也可以省略)

/**
 * 拦截器
 *
 * @author qiwu
 * <br> Date : 2021/1/23 12:29 上午
 * <br> Copyright (c) 2021/1/23 ZiYun Tech.
 */
@Configuration
public class ErrorInterceptor implements HandlerInterceptor {
    /**
     * Controller方法调用之前调用,用于接收请求
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        // 只有返回true才会继续向下执行,返回false取消当前请求
        return true;
    }

    /**
     * 请求拦截
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        if(httpServletResponse.getStatus() == 500){
            modelAndView.setViewName("/error/500");
        }
        else if(httpServletResponse.getStatus() == 404){
            modelAndView.setViewName("/error/404");
        }
    }

    /**
     * 清理资源,当preHandle方法返回true调用
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param e
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

3.6、前端页面

  • 前端默认页面static目录下的index
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h4>Thymeleaf Spring Boot web应用程序示例</h4>
</body>
</html>
  • templates目录下index
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>首页</title>
	<script src="/common/common-js.js" type="application/javascript"></script>
</head>
<body>
<div id="app">
	This is the index page of activiti!
	<el-button type="primary">测试element组件</el-button>
</div>

<script>
	new Vue({
		el: '#app',
		data: {
			message: 'Hello Vue!'
		}
	})
</script>
</body>
</html>
  • templates目录下hello
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
Thymeleaf模板引擎
<h1 th:text="${name}">hello world~~~~~~~~~~${name}</h1>
</body>
</html>
  • templates目录下error下的500
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
500
</body>
</html>
  • templates目录下error下的404
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
404
</body>
</html>

至此就结束了,现在来验证一下子

四、访问

  • 默认和访问index都是去找templates下的index页面
    image.png
    image.png
  • 访问hello
    image.png
  • 访问hello1,这时候就找不到该路由,按照理由跳转到springboot自带的错误页面,这里自定义了,所以会跳转到erroe目录下的404,500也是同理
    image.png

好了到这里就真的结束了,不过有个注意的值得注意,那就是为啥static里面也有一个index页面,请看下面注意事项

五、注意:

  • 配置里面不设置mvc.static-path-pattern: 的话并且不指定@RequestMapping("/")会默认访问static里面index文件
  • 配置里面设置mvc.static-path-pattern: /**会默认访问static里面index文件
  • 设置的话就会默认访问templates目录里面的inde文件,不需要设置@RequestMapping("/")来达到访问inde文件
  • 目录访问错误会跳到404或者500页面,ErrorInterceptor文件进行拦截