Java高级 | 【实验三】Springboot 静态资源访问

news2025/6/7 2:55:01

隶属文章: Java高级 | (二十二)Java常用类库-CSDN博客

系列文章: Java高级 | 【实验一】Spring Boot安装及测试 最新-CSDN博客

                   Java高级 | 【实验二】Springboot 控制器类+相关注解知识-CSDN博客

目录

一、Thymeleaf

1.1 是什么?

1.2 Thymeleaf机制说明

1.3 优点VS缺点

1.4 使用Thymeleaf

(1)jar包依赖

(2)在application.properties中配置thymeleaf

二、Thymeleaf语法

2.1 chongyoth属性

①文本替换(th:text)

②HTML 替换(th:utext)

2.2 其他th 属性

三、spring boot使用Thymeleaf

3.1 创建spring boot工程并默认使用thymeleaf模板引擎

3.2 编写控制器类及数据对象类

3.3 编写前端视图页面

(1)编写test1.html

(2)编写test2.html

(3)编写test3.html

(4)编写test4.html

​四、练习题

【问题】

【答案】


         Web 开发离不开动态页面的开发,很早以前企业主要使用JSP技术来开发网页,随着技术的升级更替,目前来说主流的方案是Thymeleaf

        Thymeleaf 是一个模板框架,它可以支持多种格式的内容动态渲染,功能非常强大,它天然和 HTML是相融合的,所以对于前端工程师来说它也是易于理解的。

       Springboot默认是不支持JSP的,默认使用Thymeleaf模板引擎

官方文档:Tutorial: Using Thymeleaf

一、Thymeleaf

1.1 是什么?

  1. 是一个跟 Velocity、FreeMarker 类似的模板引擎可完全替代 JSP
  2. 是一个 java 类库,它是一个 xml/xhtml/html5 的模板引擎,可以作为mvc的web应用的view层

1.2 Thymeleaf机制说明

         Thymeleaf 是服务器渲染技术,页面数据是在服务器端进行渲染的

        因此,在开发中使用Thymeleaf,并不是前后端分离

1.3 优点VS缺点

  1. 开箱即用,它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、改jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言;
  2. Thymeleaf模板页面无需服务器渲染,也可以被浏览器运行,页面简洁SpringBoot支持 Thymeleaf、Velocity、FreeMarker
  • 并不是一个高性能的引擎,适用于单体应用如果要做一个高并发的应用,选择前后端分离更好,但是作为SpringBoot推荐的模板引擎,还是需要了解一下

1.4 使用Thymeleaf

(1)jar包依赖

在pom.xml中添加如下依赖: 

//这个配置是必须的,事实上,spring boot项目创建好后,已自动添加该依赖
<dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-thymeleaf</artifactId>

</dependency>

(2)在application.properties中配置thymeleaf

//这个配置不是必须的
//但是spring.thymeleaf.mode的默认值是HTML5,其实是一个很严格的检查,改为LEGACYHTML5可以得到一个可能更友好亲切的格式要求。
spring.thymeleaf.mode = LEGACYHTML5

二、Thymeleaf语法

2.1 chongyoth属性

    html有的属性,Thymeleaf基本都有,而常用的属性大概有七八个。其中th属性执行的优先级从1~8,数字越低优先级越高。

属性

作用描述

相关属性

优先级(order)

说明

th:insert

代码块引入

th:replace, th:include

1

优先级最高,常用于公共代码块提取

三者的区别较大,若使用不恰当会破坏html结构

th:each

遍历循环元素

与 th:text、th:value 一起使用

2

优先级很高,注意修饰标签位置

th:if

条件判断

th:unless, th:switch, th:case

3

优先级较高

th:object

声明变量,配合 *{} 使用,达到偷懒的效果

-

4

优先级一般,用于简化表达

th:attr

修改任意属性

th:attrappend, th:attrprepend

5

优先级一般,实际开发中用的较少,因为有丰富的其他th属性帮忙,类似的还有th:attrappend,th:attrprepend

th:value

设置当前元素的 value 值,类似修改指定属性

th:src, th:href

6

优先级不高

th:text

设置当前元素的文本内容

th:utext

7

优先级不高,th:text会转义HTML标签,th:utext不会

th:fragment

定义代码块,供 th:insert 引用

-

8

优先级最低

文本替换(th:text

文本替换是指直接将变量的值替换到 HTML 标签的文本内容中。

在 Thymeleaf 中,可以使用th:text属性来实现文本替换。

<p th:text="${user.name}">Default Text</p>

在这个例子中,${user.name} 的值会替换 <p> 标签中的文本内容,如果user.name存在,则其值会显示在页面上;如果不存在,则显示默认文本"Default Text"。

HTML 替换(th:utext

HTML 替换是指将变量的值作为 HTML 内容插入到 HTML 标签中。在 Thymeleaf 中,可以使用th:utext属性来实现 HTML 替换。

<div th:utext="${user.description}">Default HTML</div>

在这个例子中,${user.description} 的值会被作为 HTML 内容插入到 <div> 标签中,不会被转义处理。这意味着,如果${user.description}的值包含 HTML 标签,它们会被正确地解析并显示在页面上。

2.2 其他th 属性

Thymeleaf 还提供了大量的 th 属性,这些属性可以直接在 HTML 标签中使用,其中常用 th 属性及其示例如下表。

属性

描述

示例

th:id

替换 HTML 的 id 属性

<input id="html-id" th:id="thymeleaf-id" />

th:text

文本替换,转义特殊字符

<h1 th:text="hello,bianchengbang" >hello</h1>

th:utext

文本替换,不转义特殊字符

<div th:utext="<h1>欢迎来到编程帮!</h1>" >欢迎你</div>

th:object

在父标签选择对象,子标签使用 *{…} 选择表达式选取值。
没有选择对象,那子标签使用选择表达式和 ${…} 变量表达式是一样的效果。
同时即使选择了对象,子标签仍然可以使用变量表达式。

<div th:object="${session.user}" >

<p th:text="*{fisrtName}">firstname</p>

</div>

th:value

替换 value 属性

  • <input th:value = "${user.name}" />

th:with

局部变量赋值运算

  • <div th:with="isEvens = ${prodStat.count}%2 == 0" th:text="${isEvens}"></div>

th:style

设置样式

  • <div th:style="'color:#F00; font-weight:bold'">编程帮 www.biancheng.net</div>

th:onclick

点击事件

  • <td th:onclick = "'getInfo()'"></td>

th:each

遍历,支持 Iterable、Map、数组等。
 

  • <table>
  • <tr th:each="m:${session.map}">
  • <td th:text="${m.getKey()}"></td>
  • <td th:text="${m.getValue()}"></td>
  • </tr>
  • </table>

th:if

根据条件判断是否需要展示此标签

  • <a th:if ="${userId == collect.userId}">

th:unless

和 th:if 判断相反,满足条件时不显示

  • <div th:unless="${m.getKey()=='name'}" ></div>

th:switch

与 Java 的 switch case语句类似
通常与 th:case 配合使用,根据不同的条件展示不同的内容

  • <div th:switch="${name}">
  • <span th:case="a">编程帮</span>
  • <span th:case="b">www.biancheng.net</span>
  • </div>

th:fragment

模板布局,类似 JSP 的 tag,用来定义一段被引用或包含的模板片段

  • <footer th:fragment="footer">插入的内容</footer>

th:insert

布局标签;
将使用 th:fragment 属性指定的模板片段(包含标签)插入到当前标签中。

  • <div th:insert="commons/bar::footer"></div>

th:replace

布局标签;
使用 th:fragment 属性指定的模板片段(包含标签)替换当前整个标签。

  • <div th:replace="commons/bar::footer"></div>

th:selected

select 选择框选中

  • <select>
  • <option>---</option>
  • <option th:selected="${name=='a'}">
  • 编程帮
  • </option>
  • <option th:selected="${name=='b'}">
  • www.biancheng.net
  • </option>
  • </select>

th:src

替换 HTML 中的 src 属性 

  • <img th:src="@{/asserts/img/bootstrap-solid.svg}" src="asserts/img/bootstrap-solid.svg" />

th:inline

内联属性;
该属性有 text,none,javascript 三种取值,
在 <script> 标签中使用时,js 代码中可以获取到后台传递页面的对象。

  • <script type="text/javascript" th:inline="javascript">
  • var name = /*[[${name}]]*/ 'bianchengbang';
  • alert(name)
  • </script>

th:action

替换表单提交地址

  • <form th:action="@{/user/login}" th:method="post"></form>

三、spring boot使用Thymeleaf

3.1 创建spring boot工程并默认使用thymeleaf模板引擎

    File->New->Project

至此,一个基于spring boot的web工程已创建完毕,该工程默认的前端模板是Thymeleaf

运行工程,如果能运行成功。则编写控制器类。

如果不能正常运行,请根据提示信息修改工程的配置,可能修改pom.xml,可能修改工程的结构(快捷键shift+ctrl+alt+s)等。

3.2 编写控制器类及数据对象类

在当前包com.example.thymeleaftest中创建控制器类及数据对象类。

(1)创建  MyData1类 

//存放数据对象
package com.example.thymeleaftest;

public class MyData1 {
    private int id = 0;
    private String username="";
    private String password="";
    public MyData1() {
    }
    public MyData1(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "MyData1{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

(2)编写控制器类 TestController

用于跳转到视图层并传递相关数据给指定的视图层。

package com.example.thymeleaftest;


import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.ArrayList;
import java.util.List;

@Controller//该注解表明TestController类是一个控制器
@RequestMapping("/test")//注解TestController类所有方法访问的url是http://localhost8080/test
public class TestController {
    @RequestMapping("/test1")//该方法处理的url是http://localhost8080/test/test1
    public String test1() {
        return "test1";//转发给视图test1.html
    }
    @RequestMapping("/test2")//该方法处理的url是http://localhost8080/test/test2
    public String test2(Model model) {//参数model为模型,用来存放转发到视图的数据
        String name = "Jack";
        model.addAttribute("name", name);//模型中填充数据,该数据在视图的中名称为name
        return "test2";
    }
    @RequestMapping("/test3")//该方法处理的url是http://localhost8080/test/test3
    public String test3(Model model) {
        List<MyData1> myList = new ArrayList<>();
        myList.add(new MyData1(1, "laisc", "lai1203"));
        myList.add(new MyData1(2, "admin", "admin888"));
        myList.add(new MyData1(3, "root", "root9812"));
        model.addAttribute("userlist", myList);
        return "test3";
    }
    @RequestMapping("/test4")//该方法处理的url是http://localhost8080/test/test4
    public String test4(Model model) {
        MyData1 mydata1 = new MyData1(1, "admin", "admin1234");
        model.addAttribute("data123", mydata1);
        return "test4";
    }
    @RequestMapping("/test5")//该方法处理的url是http://localhost8080/test/test2
    public String test5(HttpServletRequest request) {
        String name = "张三";
        request.setAttribute("name", name);
        return "test2";
    }
}

上面的控制类一个定义了5个方法,每个方法都定义了其前端访问的url,以及返回到视图的数据。

3.3 编写前端视图页面

前端视图用的是thymeleaf模板,而thymeleaf模板默认的路径是/resources/templates。因此,我们在templates文件夹中创建4个html页面,分别是test1.html、test2.html、test2.html和test4.html,即4个视图页面。如图4所示:

(1)编写test1.html

        该视图对应TestController控制器类的test1()方法,该方法没有传递任何数据到test1.html视图。test1.html视图直接输出“Hello, world!”,其代码如下所示。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
Hello, world!
</body>
</html>

 

说明:由于该视图没有输出变量的值,因此可以使用传统的html代码。

(2)编写test2.html

该视图对应TestController控制器类的test2()方法,该方法传递一个“name”变量到test2.html视图。test2.html视图输出“name”变量的值。其代码如下:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p th:text="'Hello, ' + ${name} + '!'"></p>
</body>
</html>
  • <html xmlns:th="http://www.thymeleaf.org">---导入thymeleaf资源说明:由于该视图要输出变量的值,因此必须使用thymeleaf+html代码。
  • <p th:text="'Hello, ' + ${name} + '!'">3333</p>----输出变量。 

(3)编写test3.html

    该视图对应TestController控制器类的test3()方法,该方法传递一个list集合到 test3.html视图,视图循环输出集合的值。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<table>
    <tr>
        <th>ID</th>
        <th>username</th>
        <th>password</th>
    </tr>
    <tr th:each="user : ${userlist}">
        <td th:text="${user.id}">-1</td>
        <td th:text="${user.username}">abc</td>
        <td th:text="${user.password}">555</td>
    </tr>
</table>
</body>
</html>

(4)编写test4.html

      该视图对应TestController控制器类的test3()方法,该方法传递一个model对象到test4.html视图.该视图把对象的值输出到超链接的参数值。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="details.html" th:href="@{http://localhost:8080/gtvg/order/details(orderId=${data123.username})}">链接1</a>
<a href="details.html" th:href="@{/order/details(orderId=${data123.username})}">链接2</a>
<a href="abc.html" th:href="'order/'+${data123.id}+'/details?orderId='+${data123.username} ">链接3</a>
<a href="abc.html" th:href="@{'/details/'+${data123.id}(orderId=${data123.username})}">链接4</a>
<a href="abc.html" th:href="@{'/details/'+${data123.id}+'/aaa'(orderId=${data123.username})}">链接5</a>
</body>
</html>


四、练习题

【问题】

编写一个控制器,产生100个学生对象,并把这些对象在html中以表格的形式输出。

【答案】

package com.example.thymeleaftest;

public class Student {
    private int id;
    private String name;
    private int age;

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    // Getter方法
    public int getId() { return id; }
    public String getName() { return name; }
    public int getAge() { return age; }
}
package com.example.thymeleaftest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.ArrayList;
import java.util.List;

@Controller
@RequestMapping("/student")
public class StudentController {

    @RequestMapping("/list")
    public String listStudents(Model model) {
        List<Student> students = new ArrayList<>();

        // 生成100个简单学生数据
        for (int i = 1; i <= 100; i++) {
            students.add(new Student(i, "学生" + i, 18 + (i % 7)));
        }

        model.addAttribute("students", students);
        return "studentList";
    }
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>学生列表</title>
</head>
<body>
<h1>学生列表</h1>
<table border="1">
    <tr>
        <th>ID</th>
        <th>姓名</th>
        <th>年龄</th>
    </tr>
    <tr th:each="student : ${students}">
        <td th:text="${student.id}"></td>
        <td th:text="${student.name}"></td>
        <td th:text="${student.age}"></td>
    </tr>
</table>
</body>
</html>

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

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

相关文章

「Java教案」Java程序的构成

课程目标 1&#xff0e;知识目标 能够按照Java标识符的命名规则&#xff0c;规范变量的命名。能够区分Java中的关键字与保留字。能够对注释进行分类&#xff0c;根据注释的用途合理的选择注释方式。 2&#xff0e;能力目标 能编写符合规范的标识符。能识别Java中的关键字和…

区块链可投会议CCF B--EDBT 2026 截止10.8 附录用率

Conference&#xff1a;EDBT: 29th International Conference on Extending Database Technology CCF level&#xff1a;CCF B Categories&#xff1a;数据库&#xff0f;数据挖掘&#xff0f;内容检索 Year&#xff1a;2026 Conference time&#xff1a;24th March - 27th…

经典ReLU回归!重大缺陷「死亡ReLU问题」已被解决

来源 &#xff5c; 机器之心 在深度学习领域中&#xff0c;对激活函数的探讨已成为一个独立的研究方向。例如 GELU、SELU 和 SiLU 等函数凭借其平滑梯度与卓越的收敛特性&#xff0c;已成为热门选择。 尽管这一趋势盛行&#xff0c;经典 ReLU 函数仍因其简洁性、固有稀疏性及…

在VSCode中开发一个uni-app项目

创建项目 使用命令行工具&#xff08;例如 vue-cli&#xff09;来创建一个新的 uni-app 项目。 创建以JavaScript开发的工程 npx degit dcloudio/uni-preset-vue#vite my-vue3-project //或者 npx degit dcloudio/uni-preset-vue#vite-alpha my-vue3-project创建以TypeScript…

Python - 爬虫;Scrapy框架之插件Extensions(四)

阅读本文前先参考 https://blog.csdn.net/MinggeQingchun/article/details/145904572 在 Scrapy 中&#xff0c;扩展&#xff08;Extensions&#xff09;是一种插件&#xff0c;允许你添加额外的功能到你的爬虫项目中。这些扩展可以在项目的不同阶段执行&#xff0c;比如启动…

Spark实战能力测评模拟题精析【模拟考】

1.println(Array(1,2,3,4,5).filter(_%20).toList() 输出结果是&#xff08;B&#xff09; A. 2 4 B. List(2,4) C. List(1,3,5) D. 1 3 5 2.println(Array("tom","team","pom") .filter(_.matches("")).toList) 输出结果为(List(tom,…

【OSG学习笔记】Day 15: 路径动画与相机漫游

本章来学习下漫游相机。 路径动画与相机漫游 本届内容比较简单&#xff0c;其实就是实现物体的运动和相机的运动 当然这两个要一起执行。 贝塞尔曲线 贝塞尔曲线&#xff08;Bzier curve&#xff09;是一种在计算机图形学、动画制作、工业设计等领域广泛应用的参数曲线&am…

PostgreSQL(PostGIS)触发器+坐标转换案例

需求&#xff0c;只录入一份坐标参考为4326的数据&#xff0c;但是发布的数据要求坐标必须是3857 对这种需求可以利用数据库触发器实现数据的同步 步骤&#xff1a; 1. 使用ArcGIS Pro创建一个名字为testfc_4326的图层&#xff0c;坐标参考为4326 2. 使用Pro再创建一个名字…

Constraints and Triggers

目录 Kinds of Constraints Single-Attribute Keys Multiattribute Key Foreign Keys Expressing Foreign Keys Enforcing Foreign-Key Constraints Actions Taken Attribute-Based Checks Timing of Checks Tuple-Based Checks Assertions Timing of Assertion Ch…

BERT:让AI真正“读懂”语言的革命

BERT&#xff1a;让AI真正“读懂”语言的革命 ——图解谷歌神作《BERT: Pre-training of Deep Bidirectional Transformers》 2018年&#xff0c;谷歌AI团队扔出一篇核弹级论文&#xff0c;引爆了整个NLP领域。这个叫BERT的模型在11项任务中屠榜&#xff0c;甚至超越人类表现…

冷雨泉教授团队:新型视觉驱动智能假肢手,拟人化抓握技术突破,助力截肢者重获生活自信

研究背景&#xff1a;日常生活中&#xff0c;健康人依靠手完成对物体的操作。对于手部截肢患者&#xff0c;手部的缺失导致他们难以有效地操作物体&#xff0c;进而影响正常的日常生活。拥有一个能够实现拟人地自然抓取多种日常物体的五指动力假手是手部截肢患者的夙愿&#xf…

pikachu靶场通关笔记14 XSS关卡10-XSS之js输出(五种方法渗透)

目录 一、源码分析 1、进入靶场 2、代码审计 二、渗透实战 1、根据提示输入tmac 2、XSS探测 3、注入Payload1 4、注入Payload2 5、注入Payload3 6、注入Payload4 7、注入Payload5 本系列为通过《pikachu靶场通关笔记》的XSS关卡(共10关&#xff09;渗透集合&#x…

李沐-动手学深度学习:RNN

1.RNN从零开始实现 import math import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2l#8.3.4节 #batch_size&#xff1a;每个小批量中子序列样本的数目&#xff0c;num_steps&#xff1a;每个子序列中预定义的时间步数 #loa…

【教学类-36-10】20250531蝴蝶图案描边,最适合大小(一页1图1图、2图图案不同、2图图案相同对称)

背景说明: 之前做了动物头像扇子(描边20),并制作成一页一套图案对称两张 【教学类-36-09】20250526动物头像扇子的描边(通义万相)对称图40张,根据图片长宽,自动旋转图片,最大化图片-CSDN博客文章浏览阅读1k次,点赞37次,收藏6次。【教学类-36-09】20250526动物头像…

高效DBA的日常运维主题沙龙

2024年11月10日&#xff0c;在宁波组织了高效DBA的日常运维沙龙活动&#xff0c;大概有20人左右现场参加。会议的主题为&#xff1a; 目标&#xff1a; 1、识别高频低效操作并制定自动化方案 2、建立关键运维指标健康度体系 3、输出可立即落地的优化清单 会议议程 一、效能瓶…

AAAI 2025论文分享│STD-PLM:基于预训练语言模型的时空数据预测与补全方法

本文详细介绍了一篇发表于人工智能顶级会议AAAI 2025的论文《STD-PLM: Understanding Both Spatial and Temporal Properties of Spatial-Temporal Data with PLM》。该论文提出了一种基于预训练语言模型&#xff08;Pre-trained Language Model‌&#xff0c;PLM&#xff09;的…

Ethernet/IP转DeviceNet网关:驱动大型矿山自动化升级的核心纽带

在大型矿山自动化系统中&#xff0c;如何高效整合新老设备、打通数据孤岛、实现统一控制&#xff0c;是提升效率与安全的关键挑战。JH-EIP-DVN疆鸿智能EtherNet/IP转DeviceNet网关&#xff0c;正是解决这一难题的核心桥梁&#xff0c;为矿山各环节注入强劲连接力&#xff1a; …

[蓝桥杯]模型染色

模型染色 题目描述 在电影《超能陆战队》中&#xff0c;小宏可以使用他的微型机器人组合成各种各样的形状。 现在他用他的微型机器人拼成了一个大玩具给小朋友们玩。为了更加美观&#xff0c;他决定给玩具染色。 小宏的玩具由 nn 个球型的端点和 mm 段连接这些端点之间的边…

卡西欧模拟器:Windows端功能强大的计算器

引言 大家还记得初中高中时期用的计算器吗&#xff1f;今天给大家分享的就是一款windows端的卡西欧计算器。 软件介绍 大家好&#xff0c;我是逍遥小欢。 CASIO fx-9860G是一款功能强大的图形计算器&#xff0c;适用于数学、科学和工程计算。以下是其主要功能和特点的详细介…

机器学习基础(三) 逻辑回归

目录 逻辑回归的概念核心思想 Sigmoid 函数 逻辑回归的原理和底层优化手段伯努利分布最大似然估计 Maximum Likelihood Estimation &#xff08;MLE&#xff09;伯努利分布的似然函数交叉熵损失函数&#xff08;Cross-Entropy Loss&#xff09;&#xff0c;也称为 对数损失&…