JavaWeb~模板引擎Thymeleaf总结

模板引擎是什么

我们前面已经了解到,一个网页页面分为静态页面和动态页面,静态页面可以就是一个简单的html文件。不能实现和服务器之间的交互,而动态页面可以和服务器之间进行数据交互,而动态页面的实现就用到了模板引擎。
模板引擎是为了使用户界面和数据分离而产生的,从字面意思上理解就是产生一个模板,然后把数据放进去,就可以生成一个html文件展示出来。

对于模板引擎的理解,可以理解为试卷,我们放入的数据就像是答案,每个人放入的数据不一样,也就是每个人填写的答案可能不一样,最终试卷的得分不一样,也就是数据放入后运行展示的效果不一样。
也可以理解为固定的会议室,如果没有会议室,我们去开会可能要自己带着凳子,而在会议室开会,我们不需要带凳子,只需要坐下即可,我们走了别人还可以继续用。

有哪些常见的模板引擎

模板引擎是动态网页发展的产物,Java中的模板引擎数量有很多,在最开始的网页开发中,广泛使用的是JSP,JSP是官方标准的模板,但是由于缺点较多,所以很多人弃用了JSP而选择第三方的引擎,现在广泛使用的模板引擎有Thymeleaf、FreeMaker、Velocity等等。

这里我们介绍的模板引擎是Thymeleaf,这个不仅当下比较流行,也是Spring Boot官方推荐的 。

下面是Thymeleaf的官方链接,点击可下载。

链接:https://www.thymeleaf.org/index.html
官方文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

Thymeleaf使用流程

1.先编写HTML模板文件,放到指定的目录中
2.创建Servlet代码
1)先初始化一个TemplateEngine实例
2)创建一个ServletContextTemplateResolver实例,并且指定要加载的模板文件的路径以及字符集
3)将需要和模板引擎关联的变量 使用WebContext来进行表示
4)进行渲染 TemplateEngine 有一个process方法来做这个事情。

0.在maven中央仓库引入依赖
在maven中搜索Thymeleaf
在这里插入图片描述
随便选择一个版本,然后复制依赖,粘贴在pom.xml文件中。
在这里插入图片描述
在这里插入图片描述
1.创建HTML文件模板,放在指定的目录下
所谓的模板文件,就是一个HTML文件,只不过将其中可变的数据给摘出来。
这里我们放在webapp/WEB-INF、template目录下。

代码如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>thymeleaf 演示</title>
</head>
<body>
这里的内容是可变的:
<!--我们希望h3标签中的内容是可变的,即这里面的内容是Servlet代码计算后得到的-->
    <h3 th:text="${message}"></h3>
</body>
</html>

h3标签中 的th 是thymeleaf的缩写,即这个属性是由thymeleaf提供。而text表示这个类型是个字符串,后面的 ${message}就是具体的变量,在服务器代码中,我们就可以通过计算将这个变量填充。

放到指定目录中:
在这里插入图片描述
2.创建Servlet代码
1)初始化TemplateEngine实例,初始化模板解析器对象,指定路径进行。

private TemplateEngine engine=new TemplateEngine();

TemplateEngine是Thymeleaf中最核心的类,Template是模板,Engine是引擎。这里创建了一个模板引擎对象,我们模板引擎的操作都是围绕这个对象来的,这个对象的功能就是渲染模板(也就是替换动态的数据)

在模板渲染之前,也就是替换模板中的变量之前,我们需要进行初始化,即让模板对象开始加载模板文件,以及告诉模板在哪里加载文件。


        //创建一个模板解析器对象
  ServletContextTemplateResolver resolver=new ServletContextTemplateResolver(this.getServletContext());
  
      //让模板解析器,加载模板文件
   //这里的前缀表示模板文件所在的目录
        //设置前缀和后缀的作用就是 告诉模板引擎,去加载这个目录下的 后缀为.html的文件到内存中,以备后用

        resolver.setPrefix("/WEB-INF/template");
        resolver.setSuffix(".html");

        resolver.setCharacterEncoding("utf-8");
        //把解析器对象,给设置到engine对象中
        engine.setTemplateResolver(resolver);

初始化的时候,需要创建一个模板解析器对象ServletContextTemplateResolver,这个对象的作用就是帮助模板对象TemplateEngine加载文件,在创建时,我们需要传入参数,这个参数就是目录中的Context上下文对象,通过this.getServletContext()方法来获得。

每一个web应用中都有一个Context对象,一个web应用中可以有多个Servlet,这些Servlet共用一个Context对象。关于Context对象,是Tomcat在加载web应用的时候所创建出来的,在Tomcat的webapps目录下,里面的每一个目录都可以视为一个web应用,在加载这些应用的时候,Tomcat会创建一个Context上下文对象,里面的多个Servlet共用这个一个对象。通过在这个对象,我们可以找到具体的文件目录

setPrefixsetSuffix是分别给解析器对象设置前缀和后缀,通过前缀,解析器就知道要加载的模板文件在哪个目录中,通过后缀,解析器就知道在这个目录中那些是模板文件。

2)进行模板渲染。

模板渲染就是将动态的数据进行替换,也就是将数据填入模板中,填入之前,先将数据和模板该填入的位置关联起来。

这里的举例是将用户输入的查询字符串作为动态数据,和模板进行关联。

      // 1.先从参数中读取出用户要传过来的message的值(从用户输入的查询字符串中读取)
        String message=req.getParameter("message");
        //2.将读取到的数据 和模板中 的数据关联起来。


        
        WebContext webContext=new WebContext(req,resp,this.getServletContext());
        webContext.setVariable("message",message);

WebContext 是一个键值对结构,作用就是将上面的模板变量${message}和动态数据进行关联。

关联完成后,进行渲染,通过process方法完成。

  //3.进行渲染
        String html= engine.process("hello",webContext);
        System.out.println(html);
        resp.getWriter().write(html);

整体代码如下:

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@WebServlet("/helloThymeleaf")
public class HelloThymeleafServlet extends HttpServlet {
    
    

    private TemplateEngine engine=new TemplateEngine();


    //所谓的初始化,就是告诉模板引擎,从那些目录中加载那些文件作为模板
    @Override
    public void init() throws ServletException {
    
    
       //在这个方法中完成Thymeleaf的初始化操作


        //创建一个模板解析器对象
        ServletContextTemplateResolver resolver=new ServletContextTemplateResolver(this.getServletContext());

      //让模板解析器,加载模板文件
   //这里的前缀表示模板文件所在的目录
        //设置前缀和后缀的作用就是 告诉模板引擎,去加载这个目录下的 后缀为.html的文件到内存中,以备后用

        resolver.setPrefix("/WEB-INF/template/");
        resolver.setSuffix(".html");

        resolver.setCharacterEncoding("utf-8");
        //把解析器对象,给设置到engine对象中
        engine.setTemplateResolver(resolver);

    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 0.在模板渲染之前,要先进行初始化(模板渲染就是替换变量
        //初始化操作只需要执行一次即可,放到init方法中来实现

        // 1.先从参数中读取出用户要传过来的message的值(从用户输入的查询字符串中读取)
        String message=req.getParameter("message");
        //2.将读取到的数据 和模板中 的数据关联起来。

        WebContext webContext=new WebContext(req,resp,this.getServletContext());
        webContext.setVariable("message",message);

        //3.进行渲染
        String html= engine.process("hello",webContext);
        System.out.println(html);
        resp.getWriter().write(html);
    }
}

hello.html模板:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>thymeleaf 演示</title>
</head>
<body>
<!--我们希望h3标签中的内容是可变的,即这里面的内容是Servlet代码计算后得到的-->
  <h3 th:text="${message}"></h3>
    <h3 th:text="${message}"></h3>
</body>
</html>

引入的依赖(在maven文件pom.xml中):

  <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>

常用标签

Thymeleaf渲染时,主要通过标签来识别并替换对应位置的内容,thymeleaf有很多很多的标签,下面是一些常用的标签。

标签 作用 举例
th:id 替换id th:id="${user.id}"
th:text 文本替换 th:text="${user.name}">bigsai
th:utext 支持html的文本替换 utext:="${htmlcontent}">content
th:object 替换对象 th:object="${user}"
th:value 替换值 th:value="${user.name}"
th:each 迭代 th:each=“student:${user}”
th:href 替换超链接 th:href="@{index.html}"
th:src 替换资源 th:src="@{index.js}"

链接表达式@{…}

Thymeleaf是一个基于HTML的模板引擎,在使用的时候,我们需要加入特定标签来声明和使用Thymeleaf语法,可以在代码中加入Thymeleaf头部标识:

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

在Thymeleaf中,如果想要引入一些资源链接,就需要使用链接表达式@{...},可以是static目录下的静态资源,也可以是互联网上的资源。

举例:
引入CSS:

<link rel="stylesheet" th:href="@{index.css}">

引入JavaScript:

<script type="text/javascript" th:src="@{index.js}"></script>

引入超链接:

<a th:href="@{index.html}">超链接</a>

变量表达式${…}

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>变量表达式</title>
</head>
<body>
    <h2 th:text="${message}"></h2>
</body>
</html>

在标签中如果想要修改一个变量,通过${…}写入变量名即可修改。

选择变量表达*{…}

变量表达式不仅可以写成 . . . , 而 且 还 可 以 写 成 ∗ . . . 但 是 , 有 一 个 重 要 的 区 别 : 星 号 语 法 是 对 选 定 的 对 象 评 估 表 达 式 , 而 不 是 整 个 上 下 文 。 也 就 是 说 , 只 要 没 有 选 定 的 对 象 , {...},而且还可以写成*{...} 但是,有一个重要的区别:星号语法是对选定的对象评估表达式,而不是整个上下文。 也就是说,只要没有选定的对象, ......{…}和*{…}的语法就完全一样。

那么如何选定对象?
通过th:object就可以选定对象。
举例:

<div th:object="${user}">
    <p>Name: <span th:text="*{name}">张三</span>.</p>
    <p>Age: <span th:text="*{age}">18</span>.</p>
    <p>Detail: <span th:text="*{detail}">好好学习</span>.</p>
</div>

上面就是选定了对象,如果没有选定对象,上面的代码完全等价于:

<div >
    <p>Name: <span th:text="*{user.name}">张三</span>.</p>
    <p>Age: <span th:text="${user.age}">18</span>.</p>
    <p>Detail: <span th:text="${user.detail}">好好学习</span>.</p>
</div>

消息表达式#{…}(了解)

消息表达式用于从消息源中提取消息内容,在大多数情况下,消息源是*.properties文件,同时也可以自定义其他的消息源。
表达语法:

<p th:utext="#{home.welcome}">Welcome to our grocery store!</p>

消息属性可以是静态值:

home.welcome=message

也可以是带有参数声明的值:

home.welcome=message wall, {0};

多个参数之间用分割.

#{messageKey(param1=value1, param2=value2)}

回顾:几个核心的类:

1.TemplateEngine 负责进行渲染,渲染指的是把动态的数据替换到HTML模板中指定的位置。
2.WebContext 负责把HTML 模板中的“变量”和Java代码中的“变量”给关联起来,直接简单的把这个对象理解成键值对结构。
把映射关系描述出来之后,交给上面的engine对象进行渲染
3.ServletContextTemplateResolver 模板解析器对象,把之前写好的HTML模板给加载过来,并告知engine.

代码举例:web版猜数字

运行效果:
在这里插入图片描述

后端用Servlet生成随机数字,并判断大小返回结果。

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Random;

@WebServlet("/guessNum")
public class GuessNumberServlet extends HttpServlet {
    
    
    private TemplateEngine engine=new TemplateEngine();

    //toGuess 表示要猜的数字
    private int toGuess=0;
    //count 表示要猜的次数
    private int count=0;

    @Override
    public void init() throws ServletException {
    
    
        //对模板引擎进行初始化
        ServletContextTemplateResolver resolver=new ServletContextTemplateResolver(this.getServletContext());
        resolver.setPrefix("/WEB-INF/template/");
        resolver.setSuffix(".html");
        resolver.setCharacterEncoding("utf-8");
        engine.setTemplateResolver(resolver);
    }

    //获取到页面的初始情况,并且初始化,生成一个带猜测的数字

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.setContentType("text/html;charset=utf-8");
        //1.生成一个待猜的数字
        Random random=new Random();
        toGuess=random.nextInt(100)+1;
        count=0;
        //2.返回页面
        WebContext webContext=new WebContext(req,resp,getServletContext());
        webContext.setVariable("newGame",true);
        engine.process("guessNum",webContext,resp.getWriter());
    }

     //处理一次猜的过程


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.setContentType("text/html;charset=utf-8");
        //1.从请求中,读取出用户提交的数字的内容
        String parameter =req.getParameter("num");
        int num=Integer.parseInt(parameter);
        String result=" ";
        //2.和toGuess 进行比较
        if(num<toGuess){
    
    
            result="猜低了";
        }else if(num>toGuess){
    
    
            result="猜高了";
        }else{
    
    
            result="猜对了";
        }
        //自增猜的次数
        count++;
        //4.构造一个结果页面,能够显示当前猜的结果
        WebContext webContext=new WebContext(req,resp,getServletContext());
        webContext.setVariable("newGame",false);
        webContext.setVariable("result",result);
        webContext.setVariable("count",count);
        engine.process("guessNum",webContext,resp.getWriter());
    }
}

前端生成模板:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>GuessNumber</title>
</head>
<body>
<form action="guessNum" method="POST">
    <input type="text" name="num">
    <input type="submit" value="猜数字">
</form>
<!--这个 th:if 是条件显式的逻辑, 如果if后为真,就显示改标签,如果为假,就不显示-->
<div th:if="${!newGame}">
<!--   这两个代码,是输入了猜测结果后才会显式,开始新游戏时不显示 -->
    <div th:text="${result}"></div>
    <div th:text="${count}"></div>
</div>

<div></div>
</body>
</html>

参考文章:
https://developer.aliyun.com/article/769977

猜你喜欢

转载自blog.csdn.net/Merciful_Lion/article/details/123622376