如何使用Thymeleaf给web项目中的网页渲染显示动态数据?

news2024/11/15 20:42:52

编译软件:IntelliJ IDEA 2019.2.4 x64
操作系统:win10 x64 位 家庭版
服务器软件:apache-tomcat-8.5.27


目录

  • 一. 什么是Thymeleaf?
  • 二. MVC
    • 2.1 为什么需要MVC?
    • 2.2 MVC是什么?
    • 2.3 MVC和三层架构之间的关系及工作流程
  • 三. Thymeleaf的工作原理
  • 四. Thymeleaf的优势
  • 五. Thymeleaf的准备知识
    • 5.1 物理视图
    • 5.2 逻辑视图
  • 六. 如何编写第一个Thymeleaf的程序?
  • 七.Thymeleaf的基本语法
    • 7.1 th名称空间
    • 7.2 修改标签的文本值(双标签)
    • 7.3 修改标签的属性值(单标签和双标签)
    • 7.4 解析URL地址
    • 7.5 获得域对象中的数据
      • 7.5.1 获取应用域对象中的数据
      • 7.5.2 获取会话域对象中的数据(Httpsession session)
      • 7.5.3 获取请求域对象中的数据(HttpservletRequest request)
    • 7.6 获得请求参数
      • 7.6.1 根据一个参数名获取一个参数值
      • 7.6.2 根据一个参数名获取多个参数值
    • 7.7 内置对象
      • 7.7.1 基本内置对象
      • 7.7.2 公共内置对象
    • 7.8 OGNL( 对象-图导航语言)
      • 7.8.1 简单对象
      • 7.8.2 稍微复杂的对象
      • 7.8.3 list集合(简单集合)
      • 7.8.4 复杂集合(list集合存储对象)
      • 7.8.5 复杂集合(map集合存储对象)
    • 7.9 分支与迭代
      • 7.9.1 分支,控制元素的是否显示
        • 7.9.1.1 th:if 和 th:unless
        • 7.9.1.2 th:switch和th:case
      • 7.9.2 迭代(遍历循环)
        • 7.9.2.1 简单数组迭代
        • 7.9.2.2 复杂数组迭代
    • 7.10 Thymeleaf包含其他模板文件
      • 7.10.1 应用场景
      • 7.10.2 操作步骤
        • ①给公共的代码片段起个名字
        • ②在其他页面根据名字引用
          • a. th:replace
          • b. th:insert
          • c. th:include
      • 7.10.3 综合案例


一. 什么是Thymeleaf?

Thymeleaf是一种用于Java web应用程序的服务器端模板引擎可以将HTML、XML、JavaScript等静态文件与动态数据(如表单数据、数据库中的数据等)结合起来,在服务器端生成动态的Web页面。

简而言之,它的主要作用就是在静态页面上渲染显示动态数据

Thymeleaf的设计目标是使Web开发变得更加自然和可维护。相比于其他模板引擎,Thymeleaf提供了更好的语法支持和功能,例如标记优雅降级、敏捷布局、动态URL、等,因此它被广泛地应用于Spring框架的开发中。


二. MVC

2.1 为什么需要MVC?

  • 提高代码的可维护性:MVC模式将应用程序分成三个互不干扰的部分,使代码更加清晰简洁,易于阅读和
  • 支持程序的可扩展性和可重用性:MVC模式使得开发人员在修改应用程序时更加轻松自如,只需要修改特定的代码库即可,而不会影响到其他部门的代码。这种思路与基于组件或者服务的方法相似。
  • 提升用户体验:MVC模式开发出来的应用程序中,UI
    界面(视图)负责直接呈现数据给用户。同时,视图也不包含任何关于业务领域或者实体(模型)的信息。控制器分离了模型和视图,对用户请求进行处理并起到转发作用,使得界面更加优秀、交互式、快速响应让用户体验更好。

2.2 MVC是什么?

MVC,英文全称为Model-View-Controller(模型-视图-控制器),它是一种常用于软件工程中的设计模式

Model模型 : javaBean(User/Book等类)

View视图 : html+服务器的动态数据

什么叫服务器的动态数据?如下图所示

在这里插入图片描述

Controller控制器 : 在web阶段可以暂时将Servlet视为控制器

2.3 MVC和三层架构之间的关系及工作流程

MVC的架构关系及相应的工作流程图解如下所示:

在这里插入图片描述

工作流程:

当浏览器向服务器发起请求时,请求被Servlet(控制器)所接收,Servlet会根据请求的内容调用Service(业务逻辑层)去处理相应的业务需求,Service会根据业务需要,会调用DAO层去处理数据,DAO层连接数据库获取相应的数据,然后回传数据给Service,Service根据数据处理好业务需求,将结果回传给Servlet,Servlet将结果传给Thymeleaf,让它渲染页面,从而生成的view对象响应给浏览器。


三. Thymeleaf的工作原理

原理:

从上节中的MVC架构工作流程图中可知,当Servlet接收到service(业务层)给的结果的时候,首先是到视图层(Thymeleaf),将动态数据和HTML进行拼接,从而产生一个View对象(视图),将view对象展示在浏览器上(用户看到的就是有动态数据的网页)


四. Thymeleaf的优势

  • SpringBoot官方推荐使用的视图模板技术,和SpringBoot完美整合
  • 不经过服务器运算仍然可以直接查看原始值,对前端工程师更友好

五. Thymeleaf的准备知识

5.1 物理视图

释义:

在Servlet中,将请求转发到一个HTML页面文件时,使用的完整的转发路径就是物理视图。

如下图所示:

在这里插入图片描述

上述图中所有的HTML页面都放在统一的目录(/WEB-INF/pages下),转发地址已经呈现出一种明显的规律。

将上面所有的物理视图抽取出来

/WEB-INF/pages/a.html
/WEB-INF/pages/abc.html
/WEB-INF/pages/admin.html

/WEB-INF/pages/index.html
/WEB-INF/pages/root.html

路径的开头都是/WEB-INF/pages/

路径的结尾都是:.html

对此,路径的开头部分我们称之为视图前缀,路径的结尾部分我们称之为视图后缀

5.2 逻辑视图

物理视图:视图前缀+逻辑视图+视图后缀

逻辑视图控制页面跳转的位置

例如:物理视图/WEB-INF/pages/a.html/WEB-INF/pages/ 是视图前缀,.html是视图后缀,中间的部分a是逻辑视图,即在servlet中页面跳转的代码语句中要写的跳转位置


六. 如何编写第一个Thymeleaf的程序?

程序需求:

在index.html中访问HelloServlet,由HelloServlet传给Thymeleaf,使其将请求域中的数据(这是给服务器的数据)渲染至admin.html,响应给浏览器

步骤:

①导入Thymeleaf的jar包(共8个)

ps:和导入Beanutils的jar包步骤一致,请自行参阅我的这篇博客Servlet 之超详解【2023年最新版】 第九节的内容。

在这里插入图片描述

②在web.xml中配置全局初始化参数

<!--thymeleaf的前缀和后缀-->
<context-param>
<param-name>view-prefix</param-name>
<param-value>/pages/</param-value>
</context-param>
<context-param>
<param-name>view-suffix</param-name>
<param-value>.html</param-value>
</context-param>

③创建Thymeleaf的模板类ViewBaseServlet(直接复制下面的代码,粘贴到自己的项目下ViewBaseServlet中即可),该类是 HttpServlet 的子类,专门处理 Web 应用程序中视图页面的呈现。在后期使用框架时,该类会被取代。

代码演示如下:

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

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


public class ViewBaseServlet extends HttpServlet {
    private TemplateEngine templateEngine;

    @Override
    public void init() throws ServletException {//对servlet初始化的(对象创建后立刻初始化)

        // 1.获取ServletContext对象
        ServletContext servletContext = this.getServletContext();

        // 2.创建Thymeleaf解析器对象
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);

        // 3.给解析器对象设置参数
        // ①HTML是默认模式,明确设置是为了代码更容易理解
        templateResolver.setTemplateMode(TemplateMode.HTML);

        // ②设置前缀
        String viewPrefix = servletContext.getInitParameter("view-prefix");

        templateResolver.setPrefix(viewPrefix);

        // ③设置后缀
        String viewSuffix = servletContext.getInitParameter("view-suffix");

        templateResolver.setSuffix(viewSuffix);

        // ④设置缓存过期时间(毫秒)
        templateResolver.setCacheTTLMs(60000L);

        // ⑤设置是否缓存
        templateResolver.setCacheable(true);

        // ⑥设置服务器端编码方式
        templateResolver.setCharacterEncoding("utf-8");

        // 4.创建模板引擎对象
        templateEngine = new TemplateEngine();

        // 5.给模板引擎对象设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);

    }
    //就是Thymeleaf要进行渲染的方法,后期如果要进行页面的渲染的话,需要调用此方法
    protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.设置响应体内容类型和字符集
        resp.setContentType("text/html;charset=UTF-8");

        // 2.创建WebContext对象
        WebContext webContext = new WebContext(req, resp, getServletContext());

        // 3.处理模板数据
        templateEngine.process(templateName, webContext, resp.getWriter());
    }
}

注意:ViewBaseServlet类里的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l0Nc0YAi-1681568688683)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681465703679.png)]

上述红框中的两个名称要和web.xml中全局初始化参数里设置的前缀名和后缀名保持一致,如下图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3nYKhec9-1681568688683)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681466113649.png)]

代码演示如下:

④创建HelloServlet(计划用HelloServlet传给thymeleaf去渲染网页,响应给客户端),并在web.xml中设置它的访问路径(/hello)

<!--  设置访问HelloServlet的路径 /hello  -->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>Servlet.HelloServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

⑤创建index.html,在其中设置访问HelloServlet的超链接(计划访问后台的HelloServlet)

代码演示如下:

<a href="hello">点击访问HelloServlet</a>

⑥HelloServlet(要通过Thymeleafi进行页面的渲染,需要继承ViewBaseServlet)

代码演示如下:

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

public class HelloServlet extends ViewBaseServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("访问到了HelloServlet类中的doGet方法");
        //这里假设业务已经处理好了,HelloServlet已经拿到了业务层传过来的结果
        System.out.println("HelloServlet已经拿到了业务层的处理结果....");

        //给响应(跳转至admin.html,并且msg的数据展示在网页上)
        String msg="这是给服务器的数据";

         //HelloServlet发送给Themeleaf,让它对页面进行渲染
        //设置请求域中的共享数据
        request.setAttribute("msg",msg);
        this.processTemplate("admin",request,response);//Themeleaf的原理也是转发

    }
}

⑦admin.html中需要写thymealf的渲染表达式

代码演示如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>admin页面</h1>
<h2 th:text="${msg}">这是服务器传过来的msg</h2>
</body>
</html>

注意:

要想使用thymealf的渲染表达式,就必须满足下面的两点要求

a.需要在html标签内设置th这个名称空间

示例代码如下:

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

b.在一个标签内通过添加属性的方式,让thymeleaf对该标签的标签体内容进行渲染(覆盖)

示例代码如下:

<h2 th:text="${msg}">放服务器传过来的msg数据</h2>

其中 $(msg},是从请求域内获得key值为msg的value值


七.Thymeleaf的基本语法

7.1 th名称空间

Thymeleaf所有的表达式都是通过属性的方式添加,th:表达式内容

添加的位置html标签的属性上

xmlns:th="http://www.thymeleaf.org"

7.2 修改标签的文本值(双标签)

语法:

th:text=“新值”

示例代码如下:

<h2 th:text="${msg}">放服务器传过来的msg数据</h2>

从请求域中获取key为msg的value值写入标签体中,原有的标签体内容会被覆盖

7.3 修改标签的属性值(单标签和双标签)

语法:

th:属性名=“新值”

示例代码如下::

<input type="text"value="这是原始值"th:value="${msg}">

7.4 解析URL地址

目的:

拿到urI中的上下文路径

语法:

@{/)

用途:

a.用在base标签上

示例代码如下:

<base href="" th:href="@{/}">

b.作为请求的路径

示例代码如下:

//写法一:
<a href="root?id=101&name=jack">Rootservlet01</a>
//写法二:
<a th:href="@{/root(id=101,name='jack',age=20)}">RootServlet02</a>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zWhfk8Pt-1681568688684)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681457648700.png)]

注意

这里存在一个问题,在以下两个html网页中,均设了使用thymeleaf去动态的获取上下文路径,使其可以被服务器将上下文路径渲染进base标签里。index网页中故意写错base标签中的href属性值(/day07_Thymeleaf_war_exploded123/),希望原来的错误href属性值可以被渲染为正确的路径(/day07_Thymeleaf_war_exploded/)

代码如下所示:

//index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <base href="/day07_Thymeleaf_war_exploded123/" th:href="@{/}">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="hello">访问HelloServlet</a>
</body>
</html>
//admin.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>

    <!--  使用Themeleaf动态获取上下文路径  -->
    <base href="" th:href="@{/}">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>admin页面</h1>
<h2 th:text="${msg}">这是服务器传过来的msg</h2>
输入: <input type="text" value="这是原始值" th:value="${msg}"><br>
<a href=-""th:href="${msg}">a标签</a><br/>
上下文路径:<h2 th:text="@{/}"></h2>

<!-- 传递参数 -->
<a href="root?id=101&name=jack">Rootservlet01</a>
<a th:href="@{/root(id=101,name='jack',age=20)}">RootServlet02</a>
</body>
</html>

代码运行后测试结果显示渲染失败

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bpp6KRQ7-1681568688684)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681460269986.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A6O0Qs3p-1681568688685)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681460509713.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n9M2mW9K-1681568688685)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681460379121.png)]

原因分析:

index.html中的base标签写入的是错误的项目路径,即无法从正确的项目路径去访问HelloServlet,自然也就不会别Thymeleaf所渲染

结论:

如果你的网页想使用thymeleaf的渲染表达式的话,就必须经过Servlet然后在经过Thymeleaf进行渲染才可以,在实际开发中项目内所有的网页都需要thymeleaf渲染(都需要过Servlet在过Thymeleaf模板引擎)

解决方案:

让index.html去过一遍servlet,将index.html移动至本地动态web项目下web/pages里,这样它可以Thymeleaf所识别,新增一个ToindexServlet,并同时在web-xml中设置访问ToindexServlet的路径

代码演示如下:


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

public class ToindexServlet extends ViewBaseServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        this.processTemplate("index",request,response);
    }
}

在浏览器地址栏里键入 “http://localhost:8080/day07_Thymeleaf_war_exploded/index”,以get形式访问ToindexServlet,调用其doGet方法对index.html进行渲染

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7N5tbd5l-1681568688686)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681462191956.png)]

附注:

在上述代码不变的前提下,你在web.xml中修改访问ToindexServlet的路径为"/index.abc" or “/index.html” 。这种写法在web.xml中没有语法问题,但是你在浏览器网址栏输入

http://localhost:8080/day07_Thymeleaf_war_exploded/index.html

时才可以访问到index.html,看似是在项目路径下直接找的index.html,实则不然,这是项目路径下键入访问ToindexServlet的路径,由它再过Thymeleaf渲染Index.html,然后再呈现在浏览器中供客户观看

7.5 获得域对象中的数据

7.5.1 获取应用域对象中的数据

语法:

ServletContext application(一般取别名为application)
${appliaction.应用域中的key值)

示例代码如下:

//在HelloServlet中设置应用域的数据
ServletContext application = request.getServletContext();
application.setAttribute("applicationMsg","这是应用域中的applicationMsg数据");
//在admin.html中设置
<!-- 从应用域中获取applicationMsg给admin渲染 -->
<p th:text="${application.applicationMsg}"></p>

注意:

${appliaction.应用域中的key值)中的application和ServletContext对象的别名没有丝毫关系,它是写死的,无论ServletContext对象的别名叫什么。

7.5.2 获取会话域对象中的数据(Httpsession session)

语法:

${session.会话域中的key值}

7.5.3 获取请求域对象中的数据(HttpservletRequest request)

语法:

${请求域中的key}

ps:详细应用在上述的章节内容已有展示,故不作涉及

7.6 获得请求参数

语法:

${param.请求参数的key值)

7.6.1 根据一个参数名获取一个参数值

案例:根据在index.html里访问adminServlet的超链接添加i请求参数,由adminServlet传给thymeleaf渲染admin.html并响应给客户端,admin.html可以获取请求参数并显示

示例代码如下:

//在index.html中访问adminServlet的超链接中添加请求参数
<a href="admin?id=101&name=jack">访问adminServlet</a>
//在adminServlet中获取请求参数并让thymeleaf渲染admin.html,响应给浏览器
String id = request.getParameter("id");
System.out.println("id="+id);
String name = request.getParameter("name");
System.out.println("name="+name);
//调用Thymeleaf渲染admin.html并响应给客户端
this.processTemplate("admin",request,response);
<!-- admin.html获取请求参数 -->
获取请求参数:
<p th:text="${param.id}"></p>
<p th:text="${param.name}"></p>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9rzc9ok7-1681568688687)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681476695423.png)]

7.6.2 根据一个参数名获取多个参数值

案例:根据在index.html里访问adminServlet的超链接添加i请求参数(同一个参数有多个残数值),由adminServlet传给thymeleaf渲染admin.html并响应给客户端,admin.html获取请求参数并显示

示例代码如下:

//在index.html中访问adminServlet的超链接中添加请求参数(同一个参数名有多个参数值)
<a href="admin?hobbys=basketball&hobbys=run&hobbys=rap">访问adminServlet</a>
//在adminServlet中获取一个参数名获取多个参数值,让thymeleaf渲染admin.html,响应给浏览器看
String[] hobbys = request.getParameterValues("hobbys");
System.out.println(Arrays.toString(hobbys));
<!-- 在admin.html中获取一个参数名获取多个参数值 --->
<p th:text="${param.hobbys}"></p>
<!-- 获取参数hobbys第一个参数值 -->
<p th:text="${param.hobbys[0]}"></p>
<!-- 获取参数hobbys第二个参数值 -->
<p th:text="${param.hobbys[1]}"></p>
<!-- 获取参数hobbys第三个参数值 -->
<p th:text="${param.hobbys[2]}"></p>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AFooGLci-1681568688687)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681478609353.png)]

7.7 内置对象

释义:

可以直接使用的对象

7.7.1 基本内置对象

常用基本内置对象:

#request就是Servlet中的HttpServletRequest对象
#response 就是Servlet中的HttpServletResponse对象
#session就是Servlet中的Httpsession对象
#servletContext就是Servlet中的ServletContext对象

案例:获取基本内置对象request的主机名

代码示例如下:

<!-- 获取基本内置对象request的主机名 -->
<p th:text="${#request.getServerName()}"></p>
<!-- 获取request的上下文路径 -->
<p th:text="${#request.getContextPath()}"></p>
.....

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kejaQL7q-1681568688687)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681479910190.png)]

7.7.2 公共内置对象

#strings提供了很多对字符串操作的方法
#arrays提供了操作数组的常用方法
#lists提供了操作List集合的捞用方法
#sets提供了操作set集合的常用方法
#maps提供了操作Map集合的常用方法

案例:演示#strings,#arrays,#lists等部分常用公共内置对象的部分常用方法

//在请求域中添加一个数据(数组)
String[] names={"java","python","lua"};
request.setAttribute("names",names);

//在请求域中添加一个数据(list集合)
List<String> list=new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
request.setAttribute("list",list);
//调用Thymeleaf渲染root.html并响应给客户端
this.processTemplate("root",request,response);
<!--Arrays中的方法:-->
<p>Arrays中的方法:</p>
<p th:text="${#arrays.length(names)}"></p>
<p th:text="${#arrays.contains(names,'java')}"></p>

<!--List中的方法:-->
<p>list中的方法:</p>
<p th:text="${#lists.size(list)}"></p>
<p th:text="${#lists.isEmpty(list)}"></p>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rsH93krC-1681568688688)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681484404862.png)]

7.8 OGNL( 对象-图导航语言)

对象-图的概念:

从根对象触发,通过特定的语法,逐层访问对象的各种属性。

简而言之:

就是将复杂的对象或者集合放在域对象内,Thymeleaf去获取这些数据在网页渲染

7.8.1 简单对象

案例:请求域内共享简单对象employee,rootServlet调用Thymeleaf渲染root.html并响应给客户端,root.html要显示动态数据(请求域内的简单对象employee)

代码示例如下:

//在rootServle中创建一个employee对象
Employee employee=new Employee(101,"张三",0,7800.0);
//请求域内共享一个简单对象
request.setAttribute("emp",employee);
//调用Thymeleaf渲染root.html并响应给客户端
this.processTemplate("root",request,response);

<p>简单对象:</p>
//emp整个对象
<p th:text="${emp}"></p>
//拿到对象emp内getId方法的返回值,下同
<p th:text="${emp.id}"></p>
<p th:text="${emp,name}"></p>
<p th:text="${emp.gender}"></p>
<p th:text="${emp.salary}"></p>
<p th:text="${emp.value}"></p>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Iu2JGDPD-1681568688688)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681486669076.png)]

7.8.2 稍微复杂的对象

案例:创建一个Employee002类,但是Employee02类中将一个Computer类作为自己的成员属性,在请求域内共享Employee002类的对象emp02,rootServlet调用Thymeleaf渲染root.html并响应给客户端,root.html要显示动态数据(请求域内的稍微复杂的对象emp02)

代码演示如下:

//创建Employee02类
public class Employee02 {
    private Integer id;
    private String name;
    private Integer gender; //0 男  1 女
    private Double salary;
    private Computer computer;//对象关联

    public Employee02(Integer id, String name, Integer gender, Double salary, Computer computer) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.salary = salary;
        this.computer = computer;
    }

    public Employee02() {
    }

    @Override
    public String toString() {
        return "Employee02{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender=" + gender +
                ", salary=" + salary +
                ", computer=" + computer +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public Computer getComputer() {
        return computer;
    }

    public void setComputer(Computer computer) {
        this.computer = computer;
    }
}

//创建Computer类 
public class Computer {
    private Integer id;
    private String brand;
    private double price;

    public Computer() {
    }

    @Override
    public String toString() {
        return "Computer{" +
                "id=" + id +
                ", brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }

    public Computer(Integer id, String brand, double price) {
        this.id = id;
        this.brand = brand;
        this.price = price;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

//在rootServle中创建一个employee02对象,渲染root.html后响应给客户端
Employee02 employee02=new Employee02(102,"熊二"1,34567d,new Computer(1,"联想",5000.0)
//请求域内共享一个稍微复杂的对象
request.setAttribute("emp02",employee02);
//调用Thymeleaf渲染root.html页面,响应给客户端
 this.processTemplate("root",request,response);
//root.html获取请求域内emp02的相关属性
复杂对象:
<div th:text="${emp02}"></div>
<div th:text="${emp02.id}"></div>
<div th:text="${emp02.name}"></div>
<div th:text="${emp02.salary}"></div>
Kdiv th:text="${emp02.computer}"></div>
//调用的是emp02的电脑对象的getId()的返回值,下同
<div th:text="{emp02.computer.id}"></div>
<div th:text="$emp02.computer.brand}"></div>
<div th:text="$empe2.computer.price}"></div>

在这里插入图片描述

7.8.3 list集合(简单集合)

案例:在请求域内共享list集合,rootServlet调用Thymeleaf渲染root.html网页并响应给客户端,root.html要显示动态数据(请求域内的list集合)

代码演示如下:

//请求域内共享一个list集合
List<String> strs=new ArrayList<>();
strs.add("法外狂徒张三");
strs.add("法外狂徒李四");
strs.add("法外狂徒王五");
request.setAttribute("strs",strs);
//调用Thymeleaf渲染root.html并响应给客户端
this.processTemplate("root",request,response);
<p>list集合</p>
<p th:text="${strs}"></p>
//从请求域中获取list集合strs中下标为0的元素(第0+1个元素),下同
<p th:text="${strs[0]}"></p>
<p th:text="${strs[1]}"></p>
<p th:text="${strs[2]}"></p>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RG3180Rr-1681568688689)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681530547699.png)]

7.8.4 复杂集合(list集合存储对象)

案例:在请求域内共享复杂集合,集合内放三个Employee类的对象,rootServlet调用Thymeleaf渲染root.html,在root.html中要显示动态数据(请求域内的复杂集合)

代码示例如下:

//请求域内共享复杂集合
List<Employee> emps=new ArrayList<>();
emps.add(new Employee(101,"法外狂徒张三",0,500000.0));
emps.add(new Employee(102,"法外狂徒李四",1,68787.0));
emps.add(new Employee(103,"法外狂徒王五",1,198687.0));
request.setAttribute("emps",emps);
//调用Thymeleaf渲染root.html并响应给客户端
this.processTemplate("root",request,response);
<p>复杂集合</p>
<p th:text="${emps}"></p>
//获取集合中第一个对象的toString()的返回值
<p th:text="${emps[0]}"></p>
//获取集合中第一个对象的getId()的返回值
<p th:text="${emps[0].id}"></p>
//获取集合中第一个对象的getName()的返回值
<p th:text="${emps[0].name}"></p>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IAVDQaD4-1681568688690)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681529287323.png)]

总结:

遇到对象就通过.属性名的方式去获取属性值(原理是调用get方法)
遇到Lst集合就通过下标获得到元素,如果元素是对象的话,还是回到上一句

7.8.5 复杂集合(map集合存储对象)

遇到Map集合就通过.key值的方式获得value值,如果value值是对象的话,遇到对象就通过.属性名的方式去获取属性值(原理是调用get方法)

案例:请求域内共享map集合,rootServlet调用Thymeleaf渲染root.html后响应给客户端,root.html要显示动态数据(请求域内的map集合)

代码示例如下:

//请求域内共享map集合
Map<String,Employee> map=new HashMap<>();
map.put("emp01",new Employee(101,"法外狂徒张三",0,500000.0));
map.put("emp02",new Employee(102,"法外狂徒李四",1,68787.0));
map.put("emp03",new Employee(103,"法外狂徒王五",1,198687.0));
request.setAttribute("map",map);
//调用Thymeleaf渲染root.html并响应给客户端
this.processTemplate("root",request,response);

<p>map集合</p>
<p th:text="${map}"></p>
//获取请求域内map集合的key值为emp01的value值
<p th:text="${map.emp01}"></p>
//获取请求域内map集合的key值为emp01的value值(对象)的getId()的返回值,下同
<p th:text="${map.emp01.id}"></p>
<p th:text="${map.emp02.name}"></p>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FMp5aWXz-1681568688690)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681529748839.png)]

7.9 分支与迭代

7.9.1 分支,控制元素的是否显示

7.9.1.1 th:if 和 th:unless

语法:

th:if="" : 值如果是true,元素就显示,值如果是false,就不显示
th:unless="" : 和if反过来即可

案例:请求域内共享msg数据,调用Thymeleaf渲染页面并呼应给客户端,页面内使用h:if
或th:unless等渲染表达式去判断msg数据的长度

代码示例如下:

//在请求域中共享msg数据   
 request.setAttribute("msg","这是msg数据");
 this.processTemplate("toif",request,response);
<p>th:if/unless</p>
<p th:text="${msg}"></p>
<p th:if="${#strings.length(msg)>5}">msg的数据长度大于5就显示</p>
<p th:if="${#strings.length(msg)<=5}">msg的数据长度小于或等于5就显示(1)</p>
<p th:unless="${#strings.length(msg)>5}">msg的数据长度小于或等于5就显示(2)</p>
<p th:unless="${not (#strings.length(msg)<=5)}">msg的数据长度小于或等于5就显示(3)</p>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oLDOexQY-1681568688690)(C:\Users\king\AppData\Roaming\Typora\typora-user-images\1681550268614.png)]

7.9.1.2 th:switch和th:case

语法:

th:switch=“” (看switch中的数据和哪个case相同,有相同的就显示哪个)
th:case=“”

案例:请求域内共享msg数据,调用Thymeleaf渲染页面并呼应给客户端,页面内使用渲染表达式th:switch和th:case去判断msg数据的长度并显示结果

代码示例如下:

request.setAttribute("msg","这是msg");
this.processTemplate("toif",request,response);
<div th:switch="${#strings.length(msg)}">
    <p th:case="1">长度为1</p>
    <p th:case="2">长度为2</p>
    <p th:case="3">长度为3</p>
    <p th:case="4">长度为4</p>
    <p th:case="5">长度为5</p>
</div>

在这里插入图片描述

7.9.2 迭代(遍历循环)

语法:

th:each=“obj,status:后台请求域中数据的key”

7.9.2.1 简单数组迭代

案例:请求域内共享一个list集合,调用thymeleaf渲染页面并响应给客户端,页面使用渲染表达式th:each去遍历请求域内list集合,在无序列表中显示

代码示例如下:

//请求域内共享一个list集合
List<String> strs=new ArrayList<>();
strs.add("法外狂徒张三");
strs.add("法外狂徒李四");
strs.add("法外狂徒王五");
request.setAttribute("strs",strs);
//迭代从请求域获得的list集合strs,并在无序列表中显示
<ul>
    <li th:each="str,status :${strs}" th:text="${str}"></li>

在这里插入图片描述

7.9.2.2 复杂数组迭代

案例:请求域内共享一个list集合(装三个Employee类的对象),调用thymeleaf渲染页面并响应给客户端,页面使用渲染表达式th:each去遍历请求域内的list集合,在表格中显示

//请求域内共享复杂集合
List<Employee> emps=new ArrayList<>();
emps.add(new Employee(101,"法外狂徒张三",0,500000.0));
emps.add(new Employee(102,"法外狂徒李四",1,68787.0));
emps.add(new Employee(103,"法外狂徒王五",1,198687.0));
request.setAttribute("emps",emps);
<table border="1" width="300px">
    <tr>
        <td>序号</td>
        <th>编号</th>
        <th>姓名</th>
        <th>性别</th>
        <th>工资</th>
    </tr>
    <tr th:each="emp,status :${emps}">
        <!--  status.index是从0开始的      -->
        <td th:text="${status.index+1}"></td>
        <td th:text="${emp.id}"></td>
        <td th:text="${emp.name}"></td>
      <!--  
		<td th:if="${emp.gender==0}" th:text="男"></td>
        <td th:if="${emp.gender==1}" th:text="女"></td>
	  -->
        <td th:text="${emp.gender==0?'':''}"></td>
        <td th:text="${emp.salary}"></td>
    </tr>
</table>

在这里插入图片描述

7.10 Thymeleaf包含其他模板文件

7.10.1 应用场景

网页内公共代码片段的提取

公共代码片段是什么?

以腾讯视频 pc端为例,无论用户点击了什么频道,网站左侧的红框部分总是在那里,不会改变

在这里插入图片描述

在这里插入图片描述

7.10.2 操作步骤

①给公共的代码片段起个名字

使用th:fragment来给这个片段命名:

样例代码如下:

<div th:fragment="abc"id="header">公共头部信息</div>

我给上述公共的代码片段命名为abc

②在其他页面根据名字引用

有三种写法,但实现的最终效果都相同

a. th:replace

效果将引入标签整体替换目标标签

特点它不会保留页面自身的标签

样例代码如下:

<div th:replace="base::abc"id="ahcden "></div>

它使用了 th:replace 属性来替换当前标签,其值为 base::abc 表示使用名为 abc 的模板作为替换内容。其中 base 是模板的前缀或命名空间,通常与模板所在的文件夹或包名相关联。此外,这个标签也有一个 id 属性,其值为 “ahcden”。

用通俗的话来讲,找存放公共代码片段的页面(base.html),在页面里找名称为abc的公共代码片段,将公共代码片段所在的标签替换使用th:replace的标签

在这里插入图片描述

b. th:insert

效果将引入标签插入到目标标签内

特点它会保留页面自身的标签

样例代码如下:

<div th:insert="base::abc"id="aheader"></div>

找存放公共代码片段的页面(base.html),在页面里找名称为abc的公共代码片段,将公共代码片段所在的标签引入到使用th:replace的标签内

在这里插入图片描述

c. th:include

效果将引入标签内容插入到目标标签内

特点它会去掉片段外层标记,同时保留页面自身标记

样例代码如下:

<div th:include="base::abc"id="aheader"></div>

找存放公共代码片段的页面(base.html),在页面里找名称为abc的公共代码片段,将公共代码片段所在的标签,去掉外层的标签将内容引入到使用th:replace的标签内

在这里插入图片描述

7.10.3 综合案例

案例需求:创建四个html(a,b,c,abc),其中abc.html放前三个html都要用到的公共代码片段,剩余三个html的内容自定义。三个html均需在首页(index.html)通过超链接访问对应的servlet,再由各自对应的servlet穿给thymeleaf渲染对应的html文件,最后响应给客户端

1.创建三个html(a,b和c)对应的servlet(AServlet,BServlet和CServlet),并在web-xml中设置对应Servlet的访问路径

代码演示如下:

//在web-xml中设置对应Servlet的访问路径
<!-- 设置访问AServlet的路径  /a -->
<servlet>
    <servlet-name>AServlet</servlet-name>
    <servlet-class>Servlet.AServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>AServlet</servlet-name>
    <url-pattern>/a</url-pattern>
</servlet-mapping>

<!-- 设置访问BServlet的路径 /b -->
<servlet>
    <servlet-name>BServlet</servlet-name>
    <servlet-class>Servlet.BServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>BServlet</servlet-name>
    <url-pattern>/b</url-pattern>
</servlet-mapping>

<!-- 设置访问CServlet的路径 /c -->
<servlet>
    <servlet-name>CServlet</servlet-name>
    <servlet-class>Servlet.CServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>CServlet</servlet-name>
    <url-pattern>/c</url-pattern>
</servlet-mapping>
//创建a.html对应的AServlet
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AServlet extends ViewBaseServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           this.processTemplate("a",request,response);
    }
}
//创建b.html对应的BServlet
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class BServlet extends ViewBaseServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.processTemplate("b",request,response);
    }
}
//创建c.html对应的CServlet
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CServlet extends ViewBaseServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.processTemplate("c",request,response);
    }
}

2.在首页(index.html)中设立访问AServlet,BServlet,CServlet的超链接,并创建abc,a,b和c.html

//在index.html中设立访问AServlet,BServlet,CServlet的超链接
<a href="a">访问AServlet</a><br>
<a href="b">访问BServlet</a><br>
<a href="c">访问CServlet</a>
//创建abc.html,它存放的是a,b和c.html都要用的公共代码片段
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <base th:href="@{/}">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div th:fragment="base" id="header">公共头部信息</div>
</body>
</html>
//创建a.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <base th:href="@{/}">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div th:include="abc::base" id="aheader"></div>
<h1>a</h1>
</body>
</html>
//创建b.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <base th:href="@{/}">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div th:include="abc::base" id="bheader"></div>
<h1>b</h1>
</body>
</html>
//创建c.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <base th:href="@{/}">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div th:include="abc::base" id="cheader"></div>
<h1>c</h1>
</body>
</html>

3.测试代码

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/420305.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI绘图体验:想象力无限,创作无穷!(文生图)

基础模型&#xff1a;3D二次元 PIXEL ART &#xff08;1&#xff09;16-bit pixel art, outside of caf on rainy day, light coming from windows, cinematic still(电影剧照), hdr (2) 16-bit pixel art, island in the clouds, by studio ghibli&#xff08;吉卜力工作室…

配置基于WSL2的Docker环境并支持CUDA

导言 Content 正如前文windows 10 开启WSL2介绍的&#xff0c;我们可以在windows10中使用linux子系统。今天本文介绍如何在此基础上安装Docker并支持在wsl中使用GPU。 准备工作 加入windows insider preview。建议选Dev通道&#xff0c;不要选Beta。 安装Nvidia WSL2-compa…

【数据结构】-计数排序

&#x1f387;作者&#xff1a;小树苗渴望变成参天大树 &#x1f389; 作者宣言&#xff1a;认真写好每一篇博客 &#x1f38a;作者gitee:link 如 果 你 喜 欢 作 者 的 文 章 &#xff0c;就 给 作 者 点 点 关 注 吧&#xff01; 文章目录前言一、计数排序二、排序算法复杂度…

Nginx网站服务配置

一、Nginx概述 1.1 Nginx概述 Nginx&#xff1a; Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器&#xff0c;而且支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件…

分布式计算技术(上):经典计算框架MapReduce、Spark 解析

当一个计算任务过于复杂不能被一台服务器独立完成的时候&#xff0c;我们就需要分布式计算。分布式计算技术将一个大型任务切分为多个更小的任务&#xff0c;用多台计算机通过网络组装起来后&#xff0c;将每个小任务交给一些服务器来独立完成&#xff0c;最终完成这个复杂的计…

07 -全局状态管理

全局状态管理 7-1&#xff1a;开篇 在上一章中我们完成了 “一半” 的文章搜索功能&#xff0c;并且留下了一些问题。那么这些历史残留的问题&#xff0c;我们将会在本章节中通过 全局状态管理工具 进行处理。 那么究竟什么是 全局状态管理工具&#xff0c;如何在 uniapp 中…

【Flutter进阶】聊一聊组件中的生命周期、状态管理及局部重绘

前言 说到生命周期&#xff0c;熟悉Android开发的小伙伴一定第一时间会想到Activity的生命周期&#xff0c;由于在Flutter中一切都是组件&#xff0c;所以组件的生命周期其实是类似的。 在这个过程中组件的状态——State就非常重要&#xff0c;它记录这整个组件内可变部分的状…

【SSM整合】1—Spring和Mybatis整合

⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ Spring专栏&#x1f449;https://blog.csdn.net/weixin_53580595/category_12279588.html SpringMVC专栏&#x1f449;htt…

linux安装kafka

目录 目录 一.安装包准备&#xff1a; 二.解压安装&#xff1a; 先将该安装包放入到/opt/install目录&#xff1a; 解压该文件到soft目录中&#xff1a; 改名&#xff0c;方便后续使用&#xff1a; 三修改其中配置和配置环境变量&#xff1a; 3.1 修改/opt/soft/kafka2…

camunda工作流引擎开发架构

Camunda的开发架构可以分为前端开发架构和后端开发架构。 前端开发架构&#xff1a; Camunda前端使用Angular框架进行开发&#xff0c;主要包括以下组件&#xff1a; 1、Cockpit&#xff1a;流程监控和管理界面。 2、Tasklist&#xff1a;任务管理和审批界面。 3、Admin&…

答题积分小程序云开发实战-开篇:项目介绍以及效果图

答题积分小程序云开发实战 开篇:项目介绍以及效果图 前言 我也看过不少的册子或者文章,大部分都很优秀,但也有的就长篇累牍,从时代背景讲起,复述各种基本概念、底层原理......嗯,看似很高级~ 但我阅读的时候,给我的感觉是,把你绕晕、把你劝退的感觉,相信大家都有同感,…

C++输入输出、缺省参数、函数重载、引用【C++初阶】

目录 一、C输入&输出 二、缺省参数 1、概念 2、分类 &#xff08;1&#xff09;全缺省 &#xff08;2&#xff09;半缺省 三、函数重载 1、概念 2、原理------名字修饰 一、C输入&输出 在C语言中&#xff0c;我们常用printf和scanf这两个函数进行输入输出。 …

产品-Axure9(英文版),.rp文件与.rplb文件的转换与区分

文章目录1、区分2、相互转换2.1 rp转为rplb2.1 rplb转为rp1、区分 rp文件是文档文件&#xff0c;可以理解为作品文件&#xff0c;自己的工作输出就是rp文件&#xff0c;图标如下。 rplb文件是库文件&#xff0c;是在制作文件过程中一个快捷库&#xff0c;图标如下 在点击绿色…

GitHub 上诞生了一个可视化低代码神器

作为开发者&#xff0c;你是否早已厌倦了日复一日的“增删改查”&#xff0c;每天都在重复造轮子&#xff0c;今天给大家推荐一款开源、靠谱、实用的低代码开发平台 -- ILLA Builder。 产品介绍 ILLA Builder 是 ILLA 的核心产品&#xff0c;是一款开源的低代码开发工具。通过…

ROS话题通信自定义+发布订阅代码--03

话题通信自定义msg 在 ROS 通信协议中&#xff0c;数据载体是一个较为重要组成部分&#xff0c;ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是&#xff0c;这些数据一般只包含一个 data 字段&#xff0c;结构的单一意味…

C++实现JPEG格式图片解析(附代码)

在网上看了好多解析JPEG图片的文章&#xff0c;多多少少都有问题&#xff0c;下面是我参考过的文章链接&#xff1a; 首先&#xff0c;解析的步骤1.读取文件的信息2.Huffman编码解码3.直流交流编码解析然而&#xff0c;读取多少个88矩阵才能解析出一个MCU呢&#xff1f;4.反量化…

8年测试老鸟总结,接口自动化测试测试用例编写(全覆盖场景)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 自动化测试&#xf…

15-721 Chapter 6 索引

最先是解释了一个古老的&#xff0c;现在没什么人用数据结构----T-tree&#xff0c;因为现代的cpu到cache和到memory差异巨大&#xff0c;同时memory的容量也变大了。 T-tree 两个key标志着范围&#xff0c;决定到哪里找key&#xff0c;然后存的都是指针&#xff0c;指向pare…

CANopen | 对象字典OD 05 - 创建对象字典变量,映射到RPDO

文章目录一、前言二、实验目的三、对象字典OD四、通过RPDO修改变量rx_Value4.1、NMT指令让CANopen从站进入操作状态4.2、RPDO修改变量rx_Value一、前言 该章节的源代码地址&#xff1a;github 以上摘自《CANopen_easy_begin》的第7章。 二、实验目的 CANopen从站有一个变量…

【博学谷学习记录】超强总结,用心分享 | 架构师 MySql扩容学习总结

文章目录1. 停机方案2.停写方案3.日志方案4.双写方案&#xff08;中小型数据&#xff09;5.平滑2N方案&#xff08;大数据量&#xff09;1. 停机方案 发布公告 为了进行数据的重新拆分&#xff0c;在停止服务之前&#xff0c;我们需要提前通知用户&#xff0c;比如&#xff1a…