Linux--迷宫探秘:从路径解析到存储哲学

上一篇博客我们说完了文件系统在硬件层面的意义,今天我们来说说文件系统在软件层是怎么管理的。

 Linux--深入EXT2文件系统:数据是如何被组织、存储与访问的?-CSDN博客

🌌 引言:文件系统的宇宙观

"在Linux的宇宙中,一切皆文件。路径是星辰的坐标,inode是物质的本质,而挂载机制则是连接平行世界的虫洞。我们每一次cdls,都是在与这个精妙的设计对话——看似简单的命令行背后,隐藏着一场关于命名、链接与空间折叠的史诗级工程。"

这本书将带你穿越:

  • 路径的递归迷宫:从根目录/出发,揭开"无限套娃"式解析的终极出口

  • dentry的缓存魔法:看内核如何用哈希表和LRU算法加速万亿次路径查找

  • 挂载的维度跳跃:理解如何让多个独立分区在用户视角无缝拼接

  • 软硬连接的量子纠缠:探索文件名与inode之间既独立又共生的奇妙关系

准备好开始这场从比特到哲学的探险了吗?🚀

一.路径解析

🌟抛砖引玉

问题:打开当前⼯作⽬录⽂件,查看当前⼯作⽬录⽂件的内容?

当前⼯作⽬录不也是⽂件吗?我们访问当前⼯作⽬录不也是只知道当前⼯作⽬录的⽂件名吗?

要访问它,不也得知道当前⼯作⽬录的inode吗?

"要打开当前目录,得先打开它的父目录?那父目录的父目录呢?" —— 这就像一场无限套娃的思维游戏🎭!

答:所以也要打开:当前⼯作⽬录的上级⽬录,额....,上级⽬录不也是⽬录吗??不还是上⾯的问题吗?
 

是的,所以类似"递归",需要把路径中所有的⽬录全部解析,出⼝是"/"根⽬录

⽽实际上,任何⽂件,都有路径,访问⽬标⽂件。

都要从根⽬录开始,依次打开每⼀个⽬录,根据⽬录名,依次访问每个⽬录下指定的⽬录,直到访问到test.c。这个过程叫做Linux路径解析。

所以,我们知道了:访问⽂件必须要有⽬录+⽂件名=路径的原因。

根⽬录固定⽂件名,inode号,⽆需查找,系统开机之后就必须知道。

可是路径谁提供?

你访问⽂件,都是指令/⼯具访问,本质是进程访问,进程有CWD!进程提供路径。

你open⽂件,提供了路径

 可是最开始的路径从哪⾥来?

  • 所以 Linux 为什么要有根目录,根目录下为什么要有那么多缺省目录?
  • 你为什么要有家目录,你自己可以新建目录?
  • 上面所有行为:本质就是在磁盘文件系统中,新建目录文件。而你新建的任何文件,都在你或者系统指定的目录下新建,这不就是天然就有路径了嘛!
  • 系统 + 用户共同构建 Linux 路径结构。
🌟 思考题解答
1. cd ~的魔法原理

# 当输入 cd ~ 时:
1. Shell会读取/etc/passwd中你的用户配置
2. 找到对应的家目录路径(如/home/yourname)
3. 通过环境变量$HOME获取该路径
4. 最终执行 cd /home/yourname

💡 秘密武器:getpwuid()系统调用负责这个转换过程!

2. 新建文件的"自动路径"奥秘

# 创建新文件时的隐藏逻辑:
1. 进程维护着当前工作目录(CWD)的inode
2. 新建文件时:
   a. 在CWD的目录数据块添加新条目
   b. 新条目自动继承完整路径前缀
3. 就像在树上长出新叶子🍃,自然带有枝干路径

🎯 关键点:路径是"从根向下生长"的,不是从文件向上回溯的!

3. 根目录inode为什么是2?

# 这个历史设计选择的原因:
1. inode 0:保留不用(错误检查)
2. inode 1:传统上用于坏块追踪
3. inode 2:因此成为根目录的"专属VIP号"

📜 Unix传统:早期文件系统需要预留特殊inode

 二.路径缓存

🌟抛砖引玉

问题 1: Linux 磁盘中,存在真正的目录吗?
答案:不存在,只有文件。只保存文件属性 + 文件内容


问题 2: 访问任何文件,都要从 / 目录开始进行路径解析?
答案:原则上是,但是这样太慢,所以 Linux 会缓存历史路径结构


问题 3: Linux 目录的概念,怎么产生的?
答案:打开的文件是目录的话,由 OS 自己在内存中进行路径维护

Linux中,在内核中维护树状路径结构的内核结构体叫做: struct dentry

struct dentry {atomic_t d_count;unsigned int d_flags;        /* protected by d_lock */spinlock_t d_lock;           /* dentry lock */struct inode *d_inode;       /* Where the name belongs to - NULL is* negative *//* The next three fields are touched by __d_lookup.  Place them here* so they all fit in a cache line.*/struct hlist_node d_hash;    /* lookup hash list */struct dentry *d_parent;     /* parent directory */struct qstr d_name;struct list_head d_lru;      /* LRU list *//** d_child and d_rcu can share memory*/union {struct list_head d_child; /* child of parent list */struct rcu_head d_rcu;} d_u;struct list_head d_subdirs;  /* our children */struct list_head d_alias;    /* inode alias list */unsigned long d_time;        /* used by d_revalidate */struct dentry_operations *d_op;struct super_block *d_sb;    /* The root of the dentry tree */void *d_fsdata;              /* fs-specific data */
#ifdef CONFIG_PROFILINGstruct dentry *d_cookie;     /* cookie, if any */
#endifint d_mounted;unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};

注意:

  • 每个文件其实都要有对应的 dentry 结构,包括普通文件。这样所有被打开的文件,就可以在内存中形成整个树形结构
  • 整个树形节点也同时会隶属于 LRU (Least Recently Used,最近最少使用) 结构中,进行节点淘汰
  • 整个树形节点也同时会隶属于 Hash,方便快速查找
  • 更重要的是,这个树形结构,整体构成了 Linux 的路径缓存结构,打开访问任何文件,都在先在这棵树下根据路径进行查找,找到就返回属性 inode 和内容,没找到就从磁盘加载路径,添加 dentry 结构,缓存新路径

 

三.挂载分区

3.1🔍 核心矛盾:跨分区的路径统一性

当系统存在多个分区时,每个分区拥有独立的inode体系(如分区A的inode=100与分区B的inode=100互不冲突)。但用户看到的却是统一的路径树,例如:

  • /home(可能位于SSD分区)

  • /mnt/data(可能挂载HDD分区)

解决方案挂载(Mount)——将分区的根目录"嫁接"到全局路径树的某个节点上,形成逻辑统一的文件系统视图。

问题不就是:inode 不是不能跨分区吗?Linux 不是可以有多个分区吗?我怎么知道我在哪一个分区???

我们用一个实验证明:

# 制作一个大的磁盘块,就当做一个分区
$ dd if=/dev/zero of=./disk.img bs=1M count=5  
# 格式化写入文件系统
$ mkfs.ext4 disk.img  
# 建立空目录
$ mkdir ./mnt/mydisk  
# 查看可以使用的分区
$ df -h  
Filesystem      Size  Used Avail Use% Mounted on
udev            956M     0  956M   0% /dev
tmpfs           199M  724K  197M   1% /run
/dev/vda1        50G   26G   28G  42% /
tmpfs           988M     0  988M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           988M     0  988M   0% /sys/fs/cgroup
tmpfs           199M     0  199M   0% /run/user/0
tmpfs           199M     0  199M   0% /run/user/1002
# 将分区挂载到指定的目录
$ sudo mount -t ext4 ./disk.img /mnt/mydisk/  
$ df -h  
Filesystem      Size  Used Avail Use% Mounted on
udev            956M     0  956M   0% /dev
tmpfs           199M  724K  197M   1% /run
/dev/vda1        50G   26G   28G  42% /
tmpfs           988M     0  988M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           988M     0  988M   0% /sys/fs/cgroup
tmpfs           199M     0  199M   0% /run/user/0
tmpfs           199M     0  199M   0% /run/user/1002
/dev/loop0      4.9M   24K  4.5M   1% /mnt/mydisk
# 卸载分区
$ sudo umount /mnt/mydisk  
$ df -h  
Filesystem      Size  Used Avail Use% Mounted on
udev            956M     0  956M   0% /dev
tmpfs           199M  724K  197M   1% /run
/dev/vda1        50G   26G   28G  42% /
tmpfs           988M     0  988M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           988M     0  988M   0% /sys/fs/cgroup
tmpfs           199M     0  199M   0% /run/user/0
tmpfs           199M     0  199M   0% /run/user/1002

注意:/dev/loop0 在 Linux 系统中代表第一个循环设备(loop device)。循环设备,也被称为回环设备或 loopback 设备,是一种伪设备(pseudo-device),它允许将文件作为块设备(block device)来使用。这种机制使得可以将文件(比如 ISO 镜像文件)挂载(mount)为文件系统,就像它们是物理磁盘分区或者外部存储设备一样

$ ls /dev/loop*
brw-rw---- 1 root disk 7, 0 Oct 17 18:24 /dev/loop0
brw-rw---- 1 root disk 7, 1 Jul 17 10:26 /dev/loop1
brw-rw---- 1 root disk 7, 2 Jul 17 10:26 /dev/loop2
brw-rw---- 1 root disk 7, 3 Jul 17 10:26 /dev/loop3
brw-rw---- 1 root disk 7, 4 Jul 17 10:26 /dev/loop4
brw-rw---- 1 root disk 7, 5 Jul 17 10:26 /dev/loop5
brw-rw---- 1 root disk 7, 6 Jul 17 10:26 /dev/loop6
crw-rw---- 1 root disk 16, 23 Jul 17 10:26 /dev/loop-control
brw-rw---- 1 root disk 7, 7 Jul 17 10:26 /dev/loop7

结论:

  • 分区,写入文件系统,无法直接使用,需要和指定的目录关联,进行挂载才能使用。
  • 所以,可以根据访问目标文件的 [路径前缀] 准确判断我在哪一个分区

3.2⚙️ 挂载机制深度解析

3.2.1 挂载点(Mount Point)的本质

  • 挂载点是一个空目录,其作用类似于"魔法门":

    • 访问/mnt/mydisk时,内核检查该目录是否被挂载

    • 若已挂载,则跳转到目标分区的根目录,后续路径解析在该分区内进行

 3.2.2 挂载表(Mount Table)
内核通过全局挂载表记录所有挂载关系,关键字段包括:

struct mount {struct dentry *mnt_mountpoint;  // 挂载点目录(如/mnt/mydisk)struct vfsmount mnt;           // 挂载的分区元数据struct super_block *mnt_sb;     // 目标分区的超级块// ...
};

挂载过程:

用户路径: /mnt/mydisk/file.txt  
内核动作:  
1. 解析到/mnt/mydisk时发现挂载点  
2. 切换到分区/dev/loop0的根目录  
3. 在分区内解析file.txt  

3.2.3 循环设备(Loop Device)的魔法

$ sudo mount -t ext4 ./disk.img /mnt/mydisk
  • disk.img是普通文件,但通过/dev/loop0被伪装成块设备

  • 内核为其分配独立的inode空间,实现"文件中的文件系统"

 三.文件系统总结

以下我们通过图示来理解:

  1. struct task_struct :进程控制块,是 Linux 中描述进程的核心结构体,里面的 fs(指向 struct fs_struct )记录进程的文件系统信息(如根目录、当前工作目录) ,files(指向 struct files_struct )管理进程打开的文件。
  2. struct fs_struct :维护进程的文件系统上下文,像根目录(root )、当前工作目录(pwd )等路径信息,让进程知道 “我在文件系统的哪里” 。
  3. struct files_struct :进程的 “打开文件表”,管理进程打开的文件描述符,通过 fd_array 等结构,记录哪些文件被进程打开,以及对应文件描述符的状态 。
  4. struct file :代表一个打开的文件实例 ,保存文件读写位置(f_pos )、文件操作方法(f_op ,关联 read/write 等函数逻辑 )、所属目录项(f_path 里的 dentry )等,是操作文件时的直接载体 。
  5. struct dentry :目录项结构体,是内存中 “目录树节点” ,关联文件的路径信息,帮系统快速定位文件在目录树中的位置,还会参与路径缓存,加速文件访问 。
  6. struct path :辅助结构体,通过 mnt(挂载相关 )和 dentry ,把文件关联到具体的挂载点与目录项,明确文件在整个文件系统挂载结构里的位置 。

 “进程 - 打开的文件 - 文件系统位置” 的关系:进程(task_struct )通过 fs_struct 知晓自己在文件系统的 “大位置”,用 files_struct 管理打开的文件;每个打开的文件对应 struct file ,它借助 path 和 dentry ,锚定到文件系统的目录树与挂载点,让系统能找到、操作实际的文件 。

四.软硬连接

4.1 硬链接:文件的“分身术”

🔍 硬链接的本质

硬链接(Hard Link)是同一个inode的多个文件名,就像一个人的多个别名。

  • 创建方式ln <源文件> <硬链接名>

  • 底层机制

    • 文件系统中,目录项(dentry)仅记录文件名 → inode的映射

    • 硬链接只是新增一个目录项指向相同inode

📊 硬链接的特性

特性说明
inode共享硬链接和源文件共用同一个inode,文件属性(权限、大小、时间戳)完全相同
链接计数inode的i_nlink字段记录硬链接数,rm命令实际是减少该计数,归零才删文件
不能跨文件系统因为不同文件系统的inode编号独立,无法直接关联
不能链接目录避免目录树形成环路(仅超级用户可ln -d,但仍不推荐)

💡 经典案例:. 和 ..

  • .:当前目录的硬链接(ls -ai可验证inode相同)

  • ..:父目录的硬链接

$ mkdir test && cd test
$ ls -ali
total 8
263466 drwxr-xr-x. 2 root root 4096 Sep 16 00:00 .   # ← 当前目录
263465 drwxr-xr-x. 3 root root 4096 Sep 15 23:59 ..  # ← 父目录

4.2 软链接:文件的“快捷方式”

🔍 软链接的本质

软链接(Symbolic Link,又称symlink)是一个独立的文件,其内容存储目标文件的路径

  • 创建方式ln -s <目标文件> <软链接名>

  • 底层机制

    • 软链接拥有自己的inode和磁盘空间(存放目标路径字符串)

    • 访问软链接时,内核递归解析指向的最终文件

📊 软链接的特性

特性说明
独立inode软链接是单独的文件,有自己的元数据和存储空间(存目标路径)
可跨文件系统因为存储的是路径字符串,可指向其他分区/NFS甚至不存在的文件
可链接目录常用于目录快捷访问(如/tmp -> /var/tmp
依赖目标文件若目标被删除,软链接成为“悬空引用”(dangling link),访问报ENOENT

💡 经典案例:系统目录的路径优化 

$ ls -l /bin/sh
lrwxrwxrwx. 1 root root 4 Apr  1  2023 /bin/sh -> bash  # /bin/sh是bash的软链接

4.3 软硬链接对比

维度硬链接软链接
inode与源文件相同独立inode
跨分区❌ 不可跨文件系统✅ 可跨文件系统
链接目标必须存在可指向不存在的路径
目录支持❌ 一般不适用(除./..✅ 支持
存储开销仅增加一个目录项占用独立inode和数据块(存路径字符串)
命令示例ln file1 file2ln -s file1 file2

4.4 软硬链接的实战用途

🛠️ 硬链接的典型场景

  1. 文件备份

    ln important.txt important_backup.txt  # 不占用额外空间,修改任一文件同步更新
  2. 防止误删

    touch data.log && ln data.log data.lock  # 删除data.log后,仍可通过data.lock访问

🛠️ 软链接的典型场景

  1. 版本切换

    ln -s python3.9 /usr/bin/python  # 动态切换默认Python版本
  2. 路径简化

    ln -s /opt/complex/path/config ~/.config  # 家目录快速访问

4.5 进阶思考:为什么硬链接不能跨分区?

根本原因

  • 硬链接依赖inode编号,而不同文件系统的inode编号独立(如ext4的inode=100和XFS的inode=100可能指向不同文件)

  • 若允许跨分区,删除源文件后,另一分区的硬链接可能指向无效数据,破坏文件系统一致性

替代方案

  • 使用软链接(存储路径而非inode)

  • 使用mount --bind挂载跨分区目录(内核维护映射关系)


🎯 终极总结

  • 硬链接是文件的“克隆体”,软链接是文件的“指针”。

  • 硬链接用于节省空间+防误删,软链接用于灵活路径管理

  • 理解ACM时间戳,可精准追踪文件变动历史。

  • 文件系统的设计,处处体现“共享与隔离”的平衡艺术。

Linux哲学
“硬链接是严谨的契约,软链接是自由的诗歌。”
—— 通过这两种链接,我们既能共享数据,又能保持系统的优雅与灵活。

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

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

相关文章

淘宝商品数据实时获取方案|API 接口开发与安全接入

在电商数据获取领域&#xff0c;除了官方 API&#xff0c;第三方数据 API 接入也是高效获取淘宝商品数据的重要途径。第三方数据 API 凭借丰富的功能、灵活的服务&#xff0c;为企业和开发者提供了多样化的数据解决方案。本文将聚焦第三方数据 API 接入&#xff0c;详细介绍其优…

什么是防抖和节流?它们有什么区别?

文章目录 一、防抖&#xff08;Debounce&#xff09;1.1 什么是防抖&#xff1f;1.2 防抖的实现 二、节流&#xff08;Throttle&#xff09;2.1 什么是节流&#xff1f;2.2 节流的实现方式 三、防抖与节流的对比四、总结 在前端开发中&#xff0c;我们经常会遇到一些高频触发的…

Springboot集成阿里云OSS上传

Springboot集成阿里云OSS上传 API 接口描述 DEMO提供的四个API接口&#xff0c;支持不同方式的文件和 JSON 数据上传&#xff1a; 1. 普通文件上传接口 上传任意类型的文件 2. JSON 字符串上传接口 上传 JSON 字符串 3. 单个 JSON 压缩上传接口 上传并压缩 JSON 字符串…

删除大表数据注意事项

数据库是否会因删除操作卡死&#xff0c;没有固定的 “安全删除条数”&#xff0c;而是受数据库配置、表结构、操作方式、当前负载等多种因素影响。以下是关键影响因素及实践建议&#xff1a; 一、导致数据库卡死的核心因素 硬件与数据库配置 CPU / 内存瓶颈&#xff1a;删除…

Redis 是单线程模型?|得物技术

一、背景 使用过Redis的同学肯定都了解过一个说法&#xff0c;说Redis是单线程模型&#xff0c;那么实际情况是怎样的呢&#xff1f; 其实&#xff0c;我们常说Redis是单线程模型&#xff0c;是指Redis采用单线程的事件驱动模型&#xff0c;只有并且只会在一个主线程中执行Re…

[特殊字符] AIGC工具深度实战:GPT与通义灵码如何彻底重构企业开发流程

&#x1f50d; 第一模块&#xff1a;理念颠覆——为什么AIGC不是“玩具”而是“效能倍增器”&#xff1f; ▍企业开发的核心痛点图谱&#xff08;2025版&#xff09; ​​研发效能瓶颈​​&#xff1a;需求膨胀与交付时限矛盾持续尖锐&#xff0c;传统敏捷方法论已触天花板​…

(LeetCode 面试经典 150 题) 169. 多数元素(哈希表 || 二分查找)

题目&#xff1a;169. 多数元素 方法一&#xff1a;二分法&#xff0c;最坏的时间复杂度0(nlogn)&#xff0c;但平均0(n)即可。空间复杂度为0(1)。 C版本&#xff1a; int nnums.size();int l0,rn-1;while(l<r){int mid(lr)/2;int ans0;for(auto x:nums){if(xnums[mid]) a…

(17)java+ selenium->自动化测试-元素定位大法之By css上

1.简介 CSS定位方式和xpath定位方式基本相同,只是CSS定位表达式有其自己的格式。CSS定位方式拥有比xpath定位速度快,且比CSS稳定的特性。下面详细介绍CSS定位方式的使用方法。相对CSS来说,具有语法简单,定位速度快等优点。 2.CSS定位优势 CSS定位是平常使用过程中非常重要…

【软考高级系统架构论文】企业集成平台的技术与应用

论文真题 企业集成平台是一个支持复杂信息环境下信息系统开发、集成和协同运行的软件支撑环境。它基于各种企业经营业务的信息特征,在异构分布环境(操作系统、网络、数据库)下为应用提供一致的信息访问和交互手段,对其上运行的应用进行管理,为应用提供服务,并支持企业信息…

i.MX8MP LVDS 显示子系统全解析:设备树配置与 DRM 架构详解

&#x1f525; 推荐&#xff1a;《Yocto项目实战教程&#xff1a;高效定制嵌入式Linux系统》 京东正版促销&#xff0c;欢迎支持原创&#xff01; 链接&#xff1a;https://item.jd.com/15020438.html i.MX8MP LVDS 显示子系统全解析&#xff1a;设备树配置与 DRM 架构详解 在…

keep-alive实现原理及Vue2/Vue3对比分析

一、keep-alive基本概念 keep-alive是Vue的内置组件&#xff0c;用于缓存组件实例&#xff0c;避免重复渲染。它具有以下特点&#xff1a; 抽象组件&#xff1a;自身不会渲染DOM&#xff0c;也不会出现在父组件链中包裹动态组件&#xff1a;缓存不活动的组件实例&#xff0c;…

安卓jetpack compose学习笔记-Navigation基础学习

目录 一、Navigation 二、BottomNavigation Compose是一个偏向静态刷新的UI组件&#xff0c;如果不想要自己管理页面切换的复杂状态&#xff0c;可以以使用Navigation组件。 页面间的切换可以NavHost&#xff0c;使用底部页面切换栏&#xff0c;可以使用脚手架的bottomBarNav…

基于大数据技术的在UGC数据分析与路线推荐的研究

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…

flask通过表单自动产生get请求的参数、form表单实现POST请求的自动提交

通过表单自动产生get请求的参数 相关代码如下&#xff1a; import flaskapp flask.Flask(__name__)app.route(/) def login():html <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><title>flask表单实现get…

《情感反诈模拟器》2025学习版

1.2 专业内容支持 67篇情感诈骗案例研究14万字心理学分析资料783条专业配音对白 二、安装与运行 2.1 系统要求 最低配置&#xff1a; 显卡&#xff1a;GTX 1060CPU&#xff1a;i5-8400存储&#xff1a;25GB空间 2.2 运行步骤 解压游戏文件&#xff08;21.7GB&#xff09;…

预训练 vs. 微调:大模型落地的核心两步,究竟有何不同?

在人工智能领域&#xff0c;尤其是自然语言处理&#xff08;NLP&#xff09;和计算机视觉&#xff08;CV&#xff09;&#xff0c;大型模型如GPT系列、BERT、Stable Diffusion等取得了令人瞩目的成就。支撑这些模型广泛应用的关键技术流程&#xff0c;通常包含两个核心阶段&…

微信原生小程序转uniapp过程及错误总结

https://ask.dcloud.net.cn/article/35786 此文章尤为重要&#xff0c;可以使用辅助工具 1、this.setData 源代码&#xff1a; this.setData({dateTime: obj.dateTime, });需更换为 this.dateTime obj.dateTime2、cookie问题 在此文章有解释 https://blog.csdn.net/ni155…

关于Spring JBDC

一、什么是Spring JDBC&#xff1f; 什么是JDBC&#xff1f; JDBC&#xff08;Java Database Connectivity&#xff09;是 Java 语言访问数据库的标准 API&#xff0c;它定义了一组接口和类&#xff0c;允许 Java 程序与各种数据库进行交互。JDBC 提供了执行 SQL 语句、处理结果…

【SpringBoot】Spring Boot实现SSE实时推送实战

以下是一个完整的基于 Spring Boot 的 Server-Sent Events (SSE) 示例&#xff0c;包括服务端和客户端的实现。 一、服务端实现 1. 创建 Spring Boot 项目 首先&#xff0c;创建一个基本的 Spring Boot 项目&#xff0c;并添加 spring-boot-starter-web 依赖。在 pom.xml 中…

若依导出模板时设置动态excel下拉框(表连接的)

若依导出模板时设置动态excel下拉框&#xff08;表连接的&#xff09; 一、问题二、解决1、实体类2.1、临时使用2.2、统一工具类3、调用 一、问题 若依导出只能&#xff1b;使用dictType、combo、comboReadDict、readConverterExp这些来控制字典的导出下拉&#xff0c;如果不是…