<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>硫灵儿网</title><link>https://www.60002.cn/</link><description>Good Luck To You!</description><item><title>Obsidian才是AI时代最强笔记软件</title><link>https://www.60002.cn/?id=8</link><description>&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;前面我们说了如果要学AI就去用 Claude Code 或者 Kiro 这类 AI 编辑器。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;周末两天，我把以前用的笔记全部迁移到 Obsidian 中来了，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;为什么用 Obsidian ，因为它是把所有笔记全部保存在本地一个文件夹，以 markdown 文件存储。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;而这类 AI 编辑器，天然地又是将一个文件夹添加入工作区，可以让 AI 帮你做任何事，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;因此，天然他们成了最强组合。&lt;/p&gt;&lt;h2 id=&quot;ai-插件&quot; class=&quot;headerLink&quot; style=&quot;scroll-margin-top: calc(var(--header-height) + .5rem); font-size: 1.5rem; margin: 1.2rem 0px; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;a href=&quot;https://www.auditdog.cn/posts/obsidian%E6%89%8D%E6%98%AFai%E6%97%B6%E4%BB%A3%E6%9C%80%E5%BC%BA%E7%AC%94%E8%AE%B0%E8%BD%AF%E4%BB%B6/#ai-%E6%8F%92%E4%BB%B6&quot; class=&quot;header-mark&quot; style=&quot;background-color: transparent; text-decoration-line: none; color: rgb(45, 150, 189); overflow-wrap: break-word;&quot;&gt;&lt;/a&gt;AI 插件&lt;/h2&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;如果你用 Claude Code 你可以直接在 Obsidian 安装&amp;nbsp;&lt;strong&gt;Claudian&lt;/strong&gt;&amp;nbsp;插件。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;如果你用 Kiro ，你可以用&amp;nbsp;&lt;strong&gt;Agent Client&lt;/strong&gt;&amp;nbsp;插件，它可以使用&amp;nbsp;&lt;strong&gt;ACP（Agent Client Protocol&lt;/strong&gt;&amp;nbsp;协议直接调用 Kiro-cli 。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;然后就可以起飞了，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;因为它们的背后都直接支持 Agent ， MCP ，它能背后完成非常多的任务。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img class=&quot;lazyautosizes lazyloaded&quot; src=&quot;https://www.auditdog.cn/images/Pasted-image-20260322211321.png&quot; data-src=&quot;/images/Pasted-image-20260322211321.png&quot; data-srcset=&quot;/images/Pasted-image-20260322211321.png, /images/Pasted-image-20260322211321.png 1.5x, /images/Pasted-image-20260322211321.png 2x&quot; data-sizes=&quot;auto&quot; alt=&quot;/images/Pasted-image-20260322211321.png&quot; title=&quot;/images/Pasted-image-20260322211321.png&quot; sizes=&quot;60px&quot; srcset=&quot;/images/Pasted-image-20260322211321.png, /images/Pasted-image-20260322211321.png 1.5x, /images/Pasted-image-20260322211321.png 2x&quot; style=&quot;border-style: none; object-fit: contain; font-family: &amp;quot;object-fit: contain;&amp;quot;; max-width: 100%; min-height: 1em;&quot;/&gt;&lt;/p&gt;&lt;h2 id=&quot;数据迁移&quot; class=&quot;headerLink&quot; style=&quot;scroll-margin-top: calc(var(--header-height) + .5rem); font-size: 1.5rem; margin: 1.2rem 0px; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;a href=&quot;https://www.auditdog.cn/posts/obsidian%E6%89%8D%E6%98%AFai%E6%97%B6%E4%BB%A3%E6%9C%80%E5%BC%BA%E7%AC%94%E8%AE%B0%E8%BD%AF%E4%BB%B6/#%E6%95%B0%E6%8D%AE%E8%BF%81%E7%A7%BB&quot; class=&quot;header-mark&quot; style=&quot;background-color: transparent; text-decoration-line: none; color: rgb(45, 150, 189); overflow-wrap: break-word;&quot;&gt;&lt;/a&gt;数据迁移&lt;/h2&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;我之前的笔记主要存在于三个地方：&lt;/p&gt;&lt;ol style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; padding-left: 2.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;emacs 中的 org mode .&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;anytype 笔记软件。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;微信公众号。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;迁移过程也非常简单，直接在对话框里告诉它你以前笔记的文件位置，你想要怎么迁移，合并，它自动分析写代码，直接帮你完成。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img class=&quot;lazyautosizes lazyloaded&quot; src=&quot;https://www.auditdog.cn/images/Pasted-image-20260322211535.png&quot; data-src=&quot;/images/Pasted-image-20260322211535.png&quot; data-srcset=&quot;/images/Pasted-image-20260322211535.png, /images/Pasted-image-20260322211535.png 1.5x, /images/Pasted-image-20260322211535.png 2x&quot; data-sizes=&quot;auto&quot; alt=&quot;/images/Pasted-image-20260322211535.png&quot; title=&quot;/images/Pasted-image-20260322211535.png&quot; sizes=&quot;60px&quot; srcset=&quot;/images/Pasted-image-20260322211535.png, /images/Pasted-image-20260322211535.png 1.5x, /images/Pasted-image-20260322211535.png 2x&quot; style=&quot;border-style: none; object-fit: contain; font-family: &amp;quot;object-fit: contain;&amp;quot;; max-width: 100%; min-height: 1em;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;我用&amp;nbsp;&lt;a href=&quot;https://github.com/qiye45/wechatDownload&quot; target=&quot;_blank&quot; rel=&quot;noopener noreffer &quot; style=&quot;background-color: transparent; text-decoration-line: none; color: rgb(45, 150, 189); overflow-wrap: break-word;&quot;&gt;wechatDownload&lt;/a&gt;&amp;nbsp;下载完我所有公众号文章，告诉它帮我进行了文本清洗后直接放到obsidian 中来，历史的 1000 多篇有用的文章全部整理进来了。&lt;/p&gt;&lt;h2 id=&quot;自动发布博客&quot; class=&quot;headerLink&quot; style=&quot;scroll-margin-top: calc(var(--header-height) + .5rem); font-size: 1.5rem; margin: 1.2rem 0px; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;a href=&quot;https://www.auditdog.cn/posts/obsidian%E6%89%8D%E6%98%AFai%E6%97%B6%E4%BB%A3%E6%9C%80%E5%BC%BA%E7%AC%94%E8%AE%B0%E8%BD%AF%E4%BB%B6/#%E8%87%AA%E5%8A%A8%E5%8F%91%E5%B8%83%E5%8D%9A%E5%AE%A2&quot; class=&quot;header-mark&quot; style=&quot;background-color: transparent; text-decoration-line: none; color: rgb(45, 150, 189); overflow-wrap: break-word;&quot;&gt;&lt;/a&gt;自动发布博客&lt;/h2&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;之前我是在 emacs 的 org mode 写文章，然后自定义了一个脚本一键发布到博客：&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;a href=&quot;https://www.auditdog.cn/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreffer &quot; style=&quot;background-color: transparent; text-decoration-line: none; color: rgb(45, 150, 189); overflow-wrap: break-word;&quot;&gt;www.auditdog.cn&lt;/a&gt;&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;当时弄这个自动化的时候我还折腾了好几天，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;但是在kiro 的帮助下，我直接在 obsidian 中对话，它直接帮我写好脚本，绑定一个快捷键 ,&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;很快搞定，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;同时我还让它把方法整理到 obsidian 形成一个新的笔记，方便下次我或者AI查看：&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img class=&quot;lazyautosizes lazyloaded&quot; src=&quot;https://www.auditdog.cn/images/Pasted-image-20260322212345.png&quot; data-src=&quot;/images/Pasted-image-20260322212345.png&quot; data-srcset=&quot;/images/Pasted-image-20260322212345.png, /images/Pasted-image-20260322212345.png 1.5x, /images/Pasted-image-20260322212345.png 2x&quot; data-sizes=&quot;auto&quot; alt=&quot;/images/Pasted-image-20260322212345.png&quot; title=&quot;/images/Pasted-image-20260322212345.png&quot; sizes=&quot;60px&quot; srcset=&quot;/images/Pasted-image-20260322212345.png, /images/Pasted-image-20260322212345.png 1.5x, /images/Pasted-image-20260322212345.png 2x&quot; style=&quot;border-style: none; object-fit: contain; font-family: &amp;quot;object-fit: contain;&amp;quot;; max-width: 100%; min-height: 1em;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;整个过程太快了。&lt;/p&gt;&lt;h2 id=&quot;丰富的插件&quot; class=&quot;headerLink&quot; style=&quot;scroll-margin-top: calc(var(--header-height) + .5rem); font-size: 1.5rem; margin: 1.2rem 0px; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;a href=&quot;https://www.auditdog.cn/posts/obsidian%E6%89%8D%E6%98%AFai%E6%97%B6%E4%BB%A3%E6%9C%80%E5%BC%BA%E7%AC%94%E8%AE%B0%E8%BD%AF%E4%BB%B6/#%E4%B8%B0%E5%AF%8C%E7%9A%84%E6%8F%92%E4%BB%B6&quot; class=&quot;header-mark&quot; style=&quot;background-color: transparent; text-decoration-line: none; color: rgb(45, 150, 189); overflow-wrap: break-word;&quot;&gt;&lt;/a&gt;丰富的插件&lt;/h2&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;Obsidian 的插件很丰富，以前的学习过程也比较费时，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;但现在我都直接在 Obsidian 里问 AI ，他直接帮我推荐我需求最符合的，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;甚至有些还可以帮我配置好，给我示例用法。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img class=&quot;lazyautosizes lazyloaded&quot; src=&quot;https://www.auditdog.cn/images/Pasted-image-20260322213823.png&quot; data-src=&quot;/images/Pasted-image-20260322213823.png&quot; data-srcset=&quot;/images/Pasted-image-20260322213823.png, /images/Pasted-image-20260322213823.png 1.5x, /images/Pasted-image-20260322213823.png 2x&quot; data-sizes=&quot;auto&quot; alt=&quot;/images/Pasted-image-20260322213823.png&quot; title=&quot;/images/Pasted-image-20260322213823.png&quot; sizes=&quot;60px&quot; srcset=&quot;/images/Pasted-image-20260322213823.png, /images/Pasted-image-20260322213823.png 1.5x, /images/Pasted-image-20260322213823.png 2x&quot; style=&quot;border-style: none; object-fit: contain; font-family: &amp;quot;object-fit: contain;&amp;quot;; max-width: 100%; min-height: 1em;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;比如，安装了 Excalidraw 手绘风图的插件，结合着 AI ，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;我直接&amp;nbsp;&lt;strong&gt;@这篇笔记&lt;/strong&gt;&amp;nbsp;告诉它：&lt;/p&gt;&lt;blockquote style=&quot;border-left: 0.5rem solid rgb(107, 214, 253); background-color: rgba(107, 214, 253, 0.2); padding: 0.25rem 0.75rem; margin: 1rem 0px; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap;&quot;&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem;&quot;&gt;@Obsidian才是AI时代最强笔记软件 帮我把这篇文章生成一个excalidraw 可视化图。&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;它就直接读取我指定的笔记，调用可视化绘制 excalidraw 图的 mcp ，直接帮我完成任务，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;而这个图，实际上我又可以把它嵌入到我的笔记里，作为内容的一部分。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;当然思维导图、流程图都可以。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;当然，这些能力你用其它AI 工具都可以完成，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;但&amp;nbsp;&lt;strong&gt;All In One&lt;/strong&gt;&amp;nbsp;的好处就是，不用你粘来粘去了，省心省力。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;更离谱的是，还有类似Excel的插件（ sheet plus ) ，你也是只需要告诉它指令，它就帮你做好。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;比如我让它构造了一些财务数据：&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img class=&quot;lazyautosizes lazyloaded&quot; src=&quot;https://www.auditdog.cn/images/Pasted-image-20260322214934.png&quot; data-src=&quot;/images/Pasted-image-20260322214934.png&quot; data-srcset=&quot;/images/Pasted-image-20260322214934.png, /images/Pasted-image-20260322214934.png 1.5x, /images/Pasted-image-20260322214934.png 2x&quot; data-sizes=&quot;auto&quot; alt=&quot;/images/Pasted-image-20260322214934.png&quot; title=&quot;/images/Pasted-image-20260322214934.png&quot; sizes=&quot;60px&quot; srcset=&quot;/images/Pasted-image-20260322214934.png, /images/Pasted-image-20260322214934.png 1.5x, /images/Pasted-image-20260322214934.png 2x&quot; style=&quot;border-style: none; object-fit: contain; font-family: &amp;quot;object-fit: contain;&amp;quot;; max-width: 100%; min-height: 1em;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;并且，这个Excel 其实也可以内嵌到笔记中来。&lt;/p&gt;&lt;h2 id=&quot;任务管理和时间记录&quot; class=&quot;headerLink&quot; style=&quot;scroll-margin-top: calc(var(--header-height) + .5rem); font-size: 1.5rem; margin: 1.2rem 0px; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;a href=&quot;https://www.auditdog.cn/posts/obsidian%E6%89%8D%E6%98%AFai%E6%97%B6%E4%BB%A3%E6%9C%80%E5%BC%BA%E7%AC%94%E8%AE%B0%E8%BD%AF%E4%BB%B6/#%E4%BB%BB%E5%8A%A1%E7%AE%A1%E7%90%86%E5%92%8C%E6%97%B6%E9%97%B4%E8%AE%B0%E5%BD%95&quot; class=&quot;header-mark&quot; style=&quot;background-color: transparent; text-decoration-line: none; color: rgb(45, 150, 189); overflow-wrap: break-word;&quot;&gt;&lt;/a&gt;任务管理和时间记录&lt;/h2&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;我之前用 3x3 APP 来进行任务规划、管理、记录挺长时间了。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;在移动端记录是我的刚需，所以我并没有采用 Obsidian 的相关的插件。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;而我做的直接是在Obsidian 中让 kiro 直接给我写代码，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;绑定快捷键可以自由双向同步我的任务：&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img class=&quot;lazyautosizes lazyloaded&quot; src=&quot;https://www.auditdog.cn/images/Pasted-image-20260322215606.png&quot; data-src=&quot;/images/Pasted-image-20260322215606.png&quot; data-srcset=&quot;/images/Pasted-image-20260322215606.png, /images/Pasted-image-20260322215606.png 1.5x, /images/Pasted-image-20260322215606.png 2x&quot; data-sizes=&quot;auto&quot; alt=&quot;/images/Pasted-image-20260322215606.png&quot; title=&quot;/images/Pasted-image-20260322215606.png&quot; sizes=&quot;60px&quot; srcset=&quot;/images/Pasted-image-20260322215606.png, /images/Pasted-image-20260322215606.png 1.5x, /images/Pasted-image-20260322215606.png 2x&quot; style=&quot;border-style: none; object-fit: contain; font-family: &amp;quot;object-fit: contain;&amp;quot;; max-width: 100%; min-height: 1em;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这是它读取 3x3 数据库拉取数据到当天的日记中，上面还有完成的任务（未显示），&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;同样我也可以在当天日记的“今日计划”中直接写待办事项，也可以直接同步到 3x3 APP 中，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;甚至我让Kiro 直接把我的需求写成了MCP ，我直接对话，它可以完成对我真实任务和时间记录的分析，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;变成我的个人教练，客观地指导我的行动：&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img class=&quot;lazyautosizes lazyloaded&quot; src=&quot;https://www.auditdog.cn/images/Pasted-image-20260322220011.png&quot; data-src=&quot;/images/Pasted-image-20260322220011.png&quot; data-srcset=&quot;/images/Pasted-image-20260322220011.png, /images/Pasted-image-20260322220011.png 1.5x, /images/Pasted-image-20260322220011.png 2x&quot; data-sizes=&quot;auto&quot; alt=&quot;/images/Pasted-image-20260322220011.png&quot; title=&quot;/images/Pasted-image-20260322220011.png&quot; sizes=&quot;60px&quot; srcset=&quot;/images/Pasted-image-20260322220011.png, /images/Pasted-image-20260322220011.png 1.5x, /images/Pasted-image-20260322220011.png 2x&quot; style=&quot;border-style: none; object-fit: contain; font-family: &amp;quot;object-fit: contain;&amp;quot;; max-width: 100%; min-height: 1em;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;( 注： 最近忙着写sw工具箱，没有在3x3里写待办，只记录了时间消耗 )&lt;/p&gt;&lt;h2 id=&quot;结语&quot; class=&quot;headerLink&quot; style=&quot;scroll-margin-top: calc(var(--header-height) + .5rem); font-size: 1.5rem; margin: 1.2rem 0px; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;a href=&quot;https://www.auditdog.cn/posts/obsidian%E6%89%8D%E6%98%AFai%E6%97%B6%E4%BB%A3%E6%9C%80%E5%BC%BA%E7%AC%94%E8%AE%B0%E8%BD%AF%E4%BB%B6/#%E7%BB%93%E8%AF%AD&quot; class=&quot;header-mark&quot; style=&quot;background-color: transparent; text-decoration-line: none; color: rgb(45, 150, 189); overflow-wrap: break-word;&quot;&gt;&lt;/a&gt;结语&lt;/h2&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这两天用下来，Obsidian + AI 编辑器 实在太强了，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;无论学习、工作、创作，真的可以省了很多事。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;当然，换笔记软件并不代表以前的无用，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;我之前通过使用 Anytype 对于&amp;nbsp;&lt;strong&gt;类 （ type )&lt;/strong&gt;&amp;nbsp;的这个概念会有更深入的认识，&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这让我迁移到 Obsidian 的时候完全也可以通过&amp;nbsp;&lt;strong&gt;笔记属性&lt;/strong&gt;&amp;nbsp;来实现。&lt;/p&gt;&lt;p style=&quot;margin-top: 0.5rem; margin-bottom: 0.5rem; color: rgb(22, 18, 9); font-family: system-ui, -apple-system, &amp;quot;Segoe UI&amp;quot;, Roboto, Emoji, Helvetica, Arial, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;我的学习和工作流又提高效率了。&lt;/p&gt;&lt;p&gt;以上内容来源于；&lt;a href=&quot;https://www.auditdog.cn/posts/obsidian%E6%89%8D%E6%98%AFai%E6%97%B6%E4%BB%A3%E6%9C%80%E5%BC%BA%E7%AC%94%E8%AE%B0%E8%BD%AF%E4%BB%B6/&quot;&gt;Obsidian才是AI时代最强笔记软件 - 逆行的狗&lt;/a&gt;&lt;/p&gt;</description><pubDate>Wed, 25 Mar 2026 21:38:59 +0800</pubDate></item><item><title>lvgl-micropython、lv_micropython和lv_binding_micropython到底啥关系？一文读懂</title><link>https://www.60002.cn/?id=5</link><description>&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/2591203/202603/2591203-20260327225455889-1396862142.png&quot; class=&quot;ls-is-cached lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/2591203/202603/2591203-20260327225455889-1396862142.png&quot; style=&quot;margin: 0px; padding: 0px; border: none; max-width: 800px; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;h1 id=&quot;一什么是-micropython&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;一、什么是 MicroPython？&lt;/h1&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;MicroPython 是面向微控制器的 Python 语言。借助 MicroPython，你可以编写 Python3 代码，甚至在资源受限的&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;裸机架构&lt;/strong&gt;上运行它。&lt;/p&gt;&lt;blockquote style=&quot;margin: 0px; padding: 5px 10px; background-image: none; border-top: none; border-right: none; border-bottom: none; border-left: 5px solid rgb(221, 221, 221); border-image: initial; color: rgb(85, 85, 85); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; color: rgb(119, 119, 119);&quot;&gt;💡 基础知识补充：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 25px; padding: 0px;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;裸机架构&lt;/strong&gt;：指没有操作系统（OS）、直接在硬件上运行程序的环境，资源（RAM、Flash 存储）非常有限，比如 ESP32、STM32 等单片机。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;Python3 兼容性&lt;/strong&gt;：MicroPython 语法高度兼容 Python 3，大幅降低了嵌入式开发的学习门槛，让熟悉 Python 的开发者能快速上手硬件开发。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;h1 id=&quot;二micropython-的核心亮点&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;二、MicroPython 的核心亮点&lt;/h1&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;紧凑高效&lt;/strong&gt;：仅需 256k 代码空间和 16k RAM 即可运行，无需依赖操作系统（也可搭配 OS 使用）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;高度兼容&lt;/strong&gt;：力求与标准 Python（即 CPython）语法、库尽可能兼容。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;跨架构支持&lt;/strong&gt;：支持 x86、x86-64、ARM、ARM Thumb、Xtensa（ESP32 采用）等主流嵌入式 CPU 架构。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;交互式开发&lt;/strong&gt;：无需「编译 - 烧录 - 重启」的繁琐流程，通过&amp;nbsp;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;REPL（交互式提示符）&lt;/strong&gt;&amp;nbsp;可直接输入命令并立即执行，实时调试代码。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;生态流行&lt;/strong&gt;：支持众多硬件平台，用户群体持续扩大，知名分支包括 CircuitPython（教育向）、MicroPython_ESP32_psRAM_LoBo（ESP32 优化版）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;嵌入式导向&lt;/strong&gt;：内置专门面向硬件的模块，例如&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;machine&lt;/code&gt;&amp;nbsp;模块，可直接操作 I/O 引脚、ADC、串口（UART）、SPI、I2C、RTC、定时器等底层硬件。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote style=&quot;margin: 0px; padding: 5px 10px; background-image: none; border-top: none; border-right: none; border-bottom: none; border-left: 5px solid rgb(221, 221, 221); border-image: initial; color: rgb(85, 85, 85); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; color: rgb(119, 119, 119);&quot;&gt;💡 基础知识补充：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 25px; padding: 0px;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;REPL&lt;/strong&gt;：Read-Eval-Print Loop（读取 - 求值 - 输出循环），类似 Python 的交互式终端，能实时验证代码，是嵌入式快速调试的核心工具。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;machine 模块&lt;/strong&gt;：MicroPython 的核心硬件操作模块，封装了所有底层硬件外设的操作接口，是嵌入式开发的基础入口。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;h1 id=&quot;三为什么选择micropython--lvgl&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;三、为什么选择「MicroPython + LVGL」？&lt;/h1&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;MicroPython 本身没有成熟的原生高级 GUI 库，而&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;LVGL（轻量级多功能图形库&lt;/strong&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;）&lt;/strong&gt;&amp;nbsp;是一款&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;面向对象、基于组件&lt;/strong&gt;的高级 GUI 库，非常适合映射到 Python 这类高级语言中。LVGL 由 C 语言实现，其 API 也是 C 语言风格。&lt;/p&gt;&lt;blockquote style=&quot;margin: 0px; padding: 5px 10px; background-image: none; border-top: none; border-right: none; border-bottom: none; border-left: 5px solid rgb(221, 221, 221); border-image: initial; color: rgb(85, 85, 85); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; color: rgb(119, 119, 119);&quot;&gt;💡 基础知识补充：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 25px; padding: 0px;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;LVGL&lt;/strong&gt;：嵌入式领域最流行的开源 GUI 库之一，专为资源受限的微控制器设计，提供按钮、标签、列表、图表等丰富 UI 组件，支持动画、触摸交互等现代 GUI 特性。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;面向对象 + 组件化&lt;/strong&gt;：LVGL 允许通过组合基础组件（如按钮 + 标签）创建复杂界面，代码复用性高，维护更便捷。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;h1 id=&quot;四使用lvgl-in-micropython的优势&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;四、使用「LVGL in MicroPython」的优势&lt;/h1&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;Python 语言开发 GUI&lt;/strong&gt;：利用 Python 的面向对象、语法简洁等特性，降低 GUI 开发复杂度。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;极短迭代周期&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;C 语言开发 GUI：每次修改需经历「改代码 → 编译 → 烧录 → 运行」，流程繁琐耗时。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;MicroPython 开发 GUI：仅需「改代码 → 运行」，还可通过 REPL 交互式调试，大幅提升迭代效率。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;抽象建模 GUI&lt;/strong&gt;：可利用 Python 的继承、闭包、列表推导式等语言特性，构建更灵活、可复用的界面逻辑。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;降低入门门槛&lt;/strong&gt;：无需掌握 C 语言即可开发嵌入式 GUI，与 CircuitPython「教育优先」的愿景高度契合，让新手更容易入门嵌入式开发。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;工具生态拓展&lt;/strong&gt;：可基于此开发更高层级的工具，例如拖拽式 GUI 设计器。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;五micropython--lvgl的应用场景&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;五、「MicroPython + LVGL」的应用场景&lt;/h1&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;GUI 快速原型开发&lt;/strong&gt;：快速搭建界面原型，验证交互逻辑。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;界面微调迭代&lt;/strong&gt;：实时调整界面样式、交互逻辑，无需编译烧录。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;模块化界面设计&lt;/strong&gt;：通过定义可复用的组合对象，构建复杂 GUI。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;教育与科普&lt;/strong&gt;：让零基础开发者快速体验嵌入式 GUI 开发。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;工具开发&lt;/strong&gt;：开发 LVGL 的可视化设计工具、调试工具等。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;六代码示例hello-world&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;六、代码示例：Hello World&lt;/h1&gt;&lt;pre class=&quot;highlighter-hljs&quot; data-mac-style=&quot;true&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; position: relative; text-wrap-mode: wrap; color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;import&amp;nbsp;lvgl&amp;nbsp;as&amp;nbsp;lvlv.init()scr&amp;nbsp;=&amp;nbsp;lv.obj()btn&amp;nbsp;=&amp;nbsp;lv.btn(scr)btn.align(lv.ALIGN.CENTER,&amp;nbsp;0,&amp;nbsp;0)label&amp;nbsp;=&amp;nbsp;lv.label(btn)label.set_text(&amp;quot;Hello&amp;nbsp;World!&amp;quot;)lv.screen_load(scr)&lt;/pre&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;import lvgl as lv&lt;/code&gt;：导入 LVGL 库，别名为&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv&lt;/code&gt;（简化调用）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv.init()&lt;/code&gt;：初始化 LVGL 图形库（必须第一步执行）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;scr = lv.obj()&lt;/code&gt;：创建&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;屏幕根对象&lt;/strong&gt;（所有 UI 组件的父容器）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;btn = lv.btn(scr)&lt;/code&gt;：在屏幕上创建一个按钮组件。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;btn.align(lv.ALIGN.CENTER, 0, 0)&lt;/code&gt;：将按钮&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;居中对齐&lt;/strong&gt;，后两个参数为 X、Y 方向偏移量（此处为 0，即完全居中）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;label = lv.label(btn)&lt;/code&gt;：在按钮上创建一个标签组件（作为按钮的子元素）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;label.set_text(&amp;quot;Hello World!&amp;quot;)&lt;/code&gt;：设置标签显示文本。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv.screen_load(scr)&lt;/code&gt;：加载并显示该屏幕。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote style=&quot;margin: 0px; padding: 5px 10px; background-image: none; border-top: none; border-right: none; border-bottom: none; border-left: 5px solid rgb(221, 221, 221); border-image: initial; color: rgb(85, 85, 85); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; color: rgb(119, 119, 119);&quot;&gt;💡 基础知识补充：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 25px; padding: 0px;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;LVGL 采用&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;父子对象模型&lt;/strong&gt;：所有 UI 元素都是&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv.obj&lt;/code&gt;&amp;nbsp;的子类，通过父子关系构建界面层级（屏幕 → 按钮 → 标签）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;align()&lt;/code&gt;&amp;nbsp;方法：用于精准控制组件位置，&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv.ALIGN.CENTER&lt;/code&gt;&amp;nbsp;是最常用的居中对齐方式。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;h1 id=&quot;七如何使用micropython--lvgl&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;七、如何使用「MicroPython + LVGL」？&lt;/h1&gt;&lt;h2 id=&quot;71-在线模拟器&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;7.1 在线模拟器&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;链接地址：&lt;a href=&quot;https://sim.lvgl.io/v9.0/micropython/ports/webassembly/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow&quot; style=&quot;margin: 0px; padding: 0px; color: rgb(0, 0, 0);&quot;&gt;https://sim.lvgl.io/v9.0/micropython/ports/webassembly/index.html&lt;/a&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/2591203/202603/2591203-20260327225455889-1791371467.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/2591203/202603/2591203-20260327225455889-1791371467.png&quot; style=&quot;margin: 0px; padding: 0px; border: none; max-width: 800px; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;h2 id=&quot;72-pc-模拟器&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;7.2 PC 模拟器&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;MicroPython 的「unix」移植版允许在 Linux 机器上构建并运行 LVGL + MicroPython；Windows 用户可通过 WSL、VirtualBox 等工具模拟 Linux 环境。&lt;/p&gt;&lt;h2 id=&quot;73-嵌入式平台&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;7.3 嵌入式平台&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;最终目标是在真实硬件上运行，&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_micropython&lt;/code&gt;（MicroPython+LVGL 的分支）已支持：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;平台：Linux、ESP32、STM32、RP2（树莓派 Pico）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;显示驱动：SDL（Linux）、X11（Linux）、ILI9341/ILI9488/GC9A01/ST7789/ST7735（ESP32 / 通用）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;输入驱动：SDL（Linux）、X11（Linux）、XPT2046/FT6X36（触摸）、ESP32 ADC（电阻触摸）&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote style=&quot;margin: 0px; padding: 5px 10px; background-image: none; border-top: none; border-right: none; border-bottom: none; border-left: 5px solid rgb(221, 221, 221); border-image: initial; color: rgb(85, 85, 85); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; color: rgb(119, 119, 119);&quot;&gt;💡 基础知识补充：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 25px; padding: 0px;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;驱动&lt;/strong&gt;：嵌入式 GUI 需要「显示驱动」（控制屏幕显示）和「输入驱动」（处理触摸 / 按键），&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_micropython&lt;/code&gt;&amp;nbsp;已封装主流硬件驱动，降低移植难度。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;RP2&lt;/strong&gt;：树莓派 Pico 系列的 RP2040 芯片，是低成本、高性能的入门级微控制器。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;h1 id=&quot;八高级特性自动生成绑定&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;八、高级特性：自动生成绑定&lt;/h1&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;LVGL 是&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_micropython&lt;/code&gt;&amp;nbsp;的&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;git 子模块&lt;/strong&gt;（方便分离维护核心库与绑定代码）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;构建&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_micropython&lt;/code&gt;&amp;nbsp;时，工具会自动扫描 LVGL C API，生成对应的 Python API。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;优势：无需手动编写绑定代码，保证 API 与 LVGL 核心库同步更新，支持任意 LVGL 版本。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;九内存管理关键注意事项&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;九、内存管理（关键注意事项）&lt;/h1&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;当 LVGL 在 MicroPython 中运行时，所有动态内存分配（&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_malloc()&lt;/code&gt;）由 MicroPython 的&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;垃圾回收（GC）&lt;/strong&gt;&amp;nbsp;管理器处理。&lt;/p&gt;&lt;h2 id=&quot;91-问题场景&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;9.1 问题场景&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;GC 无法感知&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;数据段（Data Segment）&lt;/strong&gt;&amp;nbsp;中的指针：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;全局变量指针&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;静态全局变量指针&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;静态局部变量指针&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这类指针若仅存储&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_malloc()&lt;/code&gt;&amp;nbsp;返回的地址，会被 GC 误认为「无引用」而提前回收，导致内存崩溃。&lt;/p&gt;&lt;h2 id=&quot;92-解决方法&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;9.2 解决方法&lt;/h2&gt;&lt;ol style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;将全局 / 静态局部变量替换为&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;(LV_GLOBAL_DEFAULT()-&amp;gt;_var)&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;在使用该变量的文件中包含&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_global.h&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;在&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_global.h&lt;/code&gt;&amp;nbsp;的&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_global_t&lt;/code&gt;&amp;nbsp;结构体中添加&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;_var&lt;/code&gt;&amp;nbsp;成员&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;blockquote style=&quot;margin: 0px; padding: 5px 10px; background-image: none; border-top: none; border-right: none; border-bottom: none; border-left: 5px solid rgb(221, 221, 221); border-image: initial; color: rgb(85, 85, 85); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; color: rgb(119, 119, 119);&quot;&gt;💡 基础知识补充：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 25px; padding: 0px;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;垃圾回收（GC）&lt;/strong&gt;：自动回收不再被引用的内存，避免内存泄漏，但静态 / 全局指针不在 GC 追踪范围内。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;数据段&lt;/strong&gt;：存储全局变量、静态变量的内存区域，生命周期与程序一致。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;h1 id=&quot;十回调机制交互核心&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;十、回调机制（交互核心）&lt;/h1&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;在 C 语言中，回调是函数指针；但在 MicroPython 中，需要为每个回调&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;同时注册函数指针和 Python 可调用对象&lt;/strong&gt;，因此定义了一套回调规范：&lt;/p&gt;&lt;h2 id=&quot;101-核心原理&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;10.1 核心原理&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;利用&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;void * user_data&lt;/code&gt;&amp;nbsp;字段，由 MicroPython「胶水代码」自动保存回调对应的 Python 对象：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;注册回调时，胶水代码将 Python 对象存入&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;user_data&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;触发回调时，胶水代码从&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;user_data&lt;/code&gt;&amp;nbsp;中取出 Python 对象并执行&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;102-三种回调定义方式&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;10.2 三种回调定义方式&lt;/h2&gt;&lt;ol style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;user_data&lt;/code&gt; 放在结构体中&lt;/strong&gt;：结构体包含&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;user_data&lt;/code&gt;，作为注册函数和回调函数的第一个参数。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;user_data&lt;/code&gt; 作为函数参数&lt;/strong&gt;：&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;user_data&lt;/code&gt;&amp;nbsp;作为注册函数和回调函数的最后一个参数。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;回调与&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;user_data&lt;/code&gt;&lt;/strong&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt; 同为结构体成员&lt;/strong&gt;：结构体同时包含函数指针和&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;user_data&lt;/code&gt;，函数指针接收结构体自身作为参数。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;blockquote style=&quot;margin: 0px; padding: 5px 10px; background-image: none; border-top: none; border-right: none; border-bottom: none; border-left: 5px solid rgb(221, 221, 221); border-image: initial; color: rgb(85, 85, 85); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; color: rgb(119, 119, 119);&quot;&gt;💡 基础知识补充：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 25px; padding: 0px;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;回调函数&lt;/strong&gt;：GUI 交互的核心，比如「按钮点击」「动画结束」时触发的逻辑。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;胶水代码&lt;/strong&gt;：连接 C 和 Python 的中间代码，负责数据类型转换、函数调用映射，让 Python 能调用 C 实现的 LVGL API。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;h1 id=&quot;十一lvgl-micropython-项目介绍&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 28px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;十一、&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lvgl-micropython&lt;/code&gt;&amp;nbsp;项目介绍&lt;/h1&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这是一个&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;将 LVGL 嵌入式 GUI 库绑定到 MicroPython&lt;/strong&gt;&amp;nbsp;的开源项目，是&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_micropython&lt;/code&gt;&amp;nbsp;和&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;lv_binding_micropython&lt;/code&gt;&amp;nbsp;的衍生版本，核心目标是让开发者能用 Python 语言在微控制器上开发图形界面，同时简化编译流程、统一 API 并拓展硬件支持。&lt;/p&gt;&lt;h2 id=&quot;111-核心概念与定位&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;11.1 核心概念与定位&lt;/h2&gt;&lt;blockquote style=&quot;margin: 0px; padding: 5px 10px; background-image: none; border-top: none; border-right: none; border-bottom: none; border-left: 5px solid rgb(221, 221, 221); border-image: initial; color: rgb(85, 85, 85); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 25px; padding: 0px;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;绑定（Binding）&lt;/strong&gt;&amp;nbsp;可以理解为「语言翻译器」：LVGL 是用 C 语言编写的嵌入式 GUI 框架，而这个项目通过「胶水代码」将 C 语言的 LVGL API 封装成 Python 可调用的接口，让 MicroPython 开发者能直接用 Python 操作 LVGL 的所有功能，无需编写底层 C 代码。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;MicroPython&lt;/strong&gt;：是 Python 语言的精简版，专为资源受限的微控制器（MCU）设计，内存占用极小，同时保留了 Python 简洁易用的语法和硬件访问能力。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;LVGL&lt;/strong&gt;：是嵌入式领域最流行的开源 GUI 框架之一，用 C99 实现，专为低资源设备优化，提供按钮、标签、列表、动画等丰富的 UI 组件，支持触摸交互和复杂界面布局。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;其项目目标在于：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;简化 LVGL + MicroPython 的编译流程，降低入门门槛。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;统一 API 规范，方便开发者添加新的显示 / 输入设备驱动。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;支持更多硬件连接拓扑，适配不同的嵌入式产品形态。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;优化性能：针对 RGB 总线等场景做了底层优化，提升 GUI 渲染帧率，同时减少内存占用。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;112-关键架构与特性&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;11.2 关键架构与特性&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;项目重构了依赖逻辑：&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;不再是 MicroPython 的附属组件，而是让 MicroPython 成为本项目的依赖&lt;/strong&gt;。这一改动极大简化了 MicroPython 版本升级的适配工作，仅需少量修改即可支持新版 MicroPython，避免了过去频繁重构绑定代码的麻烦。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;项目提供&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;make.py&lt;/code&gt;&amp;nbsp;Python 脚本统一处理编译，支持主流嵌入式平台：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;目标平台：ESP32、STM32、RP2（树莓派 Pico）、Renesas RA、nRF、i.MX RT、SAMD 等，同时支持 Unix/macOS 桌面端模拟（方便调试）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;构建依赖：需要 Python ≥ 3.10 和 C 编译器（gcc/clang/msvc），不同平台需安装对应工具链（如 ESP32 需&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;build-essential&lt;/code&gt;、&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;cmake&lt;/code&gt;&amp;nbsp;等）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;注意：Windows 平台暂未支持，macOS/Unix 版本需在本机编译后直接运行。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;113-支持和特性&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;11.3 支持和特性&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;支持绝大多数主流 LCD 驱动芯片，包括：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;常用型号：GC9A01、ILI9341、ILI9488、ST7789、ST7796 等。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;兼容方案：未列出的 IC 可通过通用&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;rgb_display&lt;/code&gt;&amp;nbsp;驱动适配。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;覆盖主流电容 / 电阻触摸芯片：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;电容触摸：CST816S、FT6x36、GT911 等。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;电阻触摸：XPT2046、STMPE610 等。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;特殊驱动：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;SDL2：仅用于 Unix/macOS 桌面端，可在电脑上模拟 LCD 显示和输入，无需烧录到硬件即可调试 GUI 代码。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;针对 RGB 总线显示场景做了关键优化：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;将全帧缓冲移至 C 层，用户只需分配部分缓冲，减少内存占用。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;利用 ESP32 第二个核心异步处理缓冲复制和屏幕旋转，避免阻塞用户 Python 代码，提升渲染帧率。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;代价是额外占用几百 KB 内存，适合有 PSRAM 的 ESP32 型号。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;核心价值在于：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;降低嵌入式 GUI 开发门槛&lt;/strong&gt;：Python 开发者无需学习 C 语言，就能快速开发嵌入式界面，利用 Python 语法优势（面向对象、迭代调试）提升效率。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;保持嵌入式性能&lt;/strong&gt;：底层仍依赖 LVGL 的 C 语言实现，保证了资源受限设备上的运行效率，同时 Python 层的薄封装几乎无额外开销。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;生态拓展&lt;/strong&gt;：支持海量硬件平台和驱动，适配从消费电子到工业控制的多种嵌入式产品形态。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;114-使用时注意&quot; style=&quot;margin: 20px 0px; padding: 0px; font-size: 21px; line-height: 1.5; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;11.4 使用时注意&lt;/h2&gt;&lt;ul style=&quot;margin-bottom: 1em; margin-left: 40px; padding: 0px; color: rgb(51, 51, 51); font-family: &amp;quot;PingFang SC&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;克隆仓库时&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;不要手动初始化子模块&lt;/strong&gt;，需按项目指定命令克隆。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;更新代码时需删除本地副本并重新克隆，避免子模块冲突。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;不可使用官方 LVGL-MicroPython 绑定的编译信息，否则会编译失败。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;硬件变体（Variant）需在指定开发板（Board）后才能配置，否则会报错。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Thu, 12 Mar 2026 16:17:07 +0800</pubDate></item><item><title>ARM 架构 JuiceFS 性能优化：基于 MLPerf 的实践与调优</title><link>https://www.60002.cn/?id=7</link><description>&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;随着国产芯片与 ARM 生态的快速发展，如何在 ARM 平台上构建高性能存储基础设施成为技术焦点。Linaro 是一个专注于 Arm 生态和开源软件的国际化技术组织，联合产业链上下游厂商解决共性问题，并协助企业客户在开源基础上完成产品化落地。Linaro 团队在 MLPerf Storage 测试中，对 JuiceFS 社区版（元数据采用 Redis）进行了系统压测，覆盖多种典型机器学习训练负载。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;测试结果显示，系统性能在很大程度上受内存带宽和元数据访问效率影响，JuiceFS 的吞吐能力直接决定 GPU 利用率及训练效率。通过 UNet3D、ResNet-50 和 CosmoFlow 等负载的测试，分析发现：单机场景下，GPU 利用率主要受内存拷贝延迟限制；在双机或多机场景下，元数据访问和节点间同步成为主要瓶颈。文章同时提供了针对这些瓶颈的调优思路与实践结果。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;总体来看，大规模 AI 训练性能调优是一个系统工程，需要从存储系统、内存带宽、CPU 调度、缓存策略等多方面协同优化，才能在 ARM 平台上实现高效的深度学习训练数据供给。&lt;/p&gt;&lt;h2 id=&quot;01-arm64-与-x86_64-架构差异与并发特性概述&quot; style=&quot;margin: 20px 0px;padding: 0px;font-size: 21px;line-height: 1.5;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;01 Arm64 与 x86_64 架构差异与并发特性概述&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;相比 x86，Arm 的应用范围不断扩大，已从移动端延伸至 IoT、可穿戴设备、PC、汽车和服务器，其高能效比（performance per watt）是广泛采用的关键原因。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;从架构设计上看，Arm 属于 RISC（Reduced Instruction Set Computer，精简指令集计算机），x86 属于 CISC（Complex Instruction Set Computer，复杂指令集计算机）。这种设计差异也影响了处理器的执行方式。Arm64 的指令长度固定为 4 字节，而 x86 指令长度可变，大约在 1–15 字节 之间，因此 x86 往往需要更复杂的译码器。相比之下，Arm 的指令更简洁，也更依赖编译器和代码生成阶段对指令的有效组织，所以需要更长的编译时间。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;从工程师可感知的角度来看，还有一些架构差异会直接影响程序行为。&lt;strong style=&quot;;padding: 0px&quot;&gt;很多在 x86 上看起来符合直觉的代码，在 Arm 上未必如此，后面要讲到的几个容易踩坑的点，基本都与这些底层差异有关&lt;/strong&gt;。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;其中一个典型问题是原子操作对地址对齐有要求。无论是 LL/SC（Load-Link/Store-Conditional），还是 LSE（Large System Extensions），在执行原子加减等读改写操作时，通常都要求访问地址满足对齐条件。较新的 LSE2 对这一限制有所放宽，开始支持 16-byte window 内的非对齐访问。数据对齐对于 x86 来说不是必须的，但保持良好对齐有助于提升性能。参考文档:&amp;nbsp;&lt;a href=&quot;https://developer.arm.com/documentation/ddi0487/maa/-Part-B-The-AArch64-Application-Level-Architecture/-Chapter-B2-The-AArch64-Application-Level-Memory-Model/-B2-8-Alignment-support/-B2-8-2-Alignment-of-data-accesses?lang=en#chdffegj&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow&quot; style=&quot;;padding: 0px;color: rgb(0, 0, 0)&quot;&gt;Arm Architecture Reference Manual for A-profile architecture&lt;/a&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;另一个需要重点关注的特点是，Arm 采用的是弱内存序模型（weakly ordered / relaxed memory model），差别体现在对内存访问顺序的约束强弱不同。在多线程场景下，同样的读写操作，在 x86 上通常更容易表现为接近程序书写顺序，而在 Arm 上则允许更多重排序，因此其他线程观察到的读写顺序可能与源码顺序不一致。在 Arm 上出现的异常需要特别考虑内存序的影响。更多细节可参考 Arm 白皮书：&lt;a href=&quot;https://developer.arm.com/documentation/107630/1-0/?lang=en&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow&quot; style=&quot;;padding: 0px;color: rgb(0, 0, 0)&quot;&gt;Synchronization Overview and Case Study on Arm Architecture&lt;/a&gt;。&lt;/p&gt;&lt;h2 id=&quot;02-juicefs-与-mlperf-概述&quot; style=&quot;margin: 20px 0px;padding: 0px;font-size: 21px;line-height: 1.5;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;02 JuiceFS 与 MLPerf 概述&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;JuiceFS 是一款开源高性能分布式文件系统，基于对象存储构建，在充分利用对象存储低成本优势的同时，提供接近传统文件系统的使用体验。它支持 POSIX、HDFS SDK、Python SDK 以及 S3 兼容接口，并能适配不同类型的应用和数据处理框架；同时支持云原生扩展、数据安全与压缩，可广泛应用于 AI 训练、推理、大数据处理等场景。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153007590-1324747406.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153007590-1324747406.png&quot; style=&quot;;padding: 0px;border: none;max-width: 800px;height: auto !important;cursor: zoom-in;transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;为评估 JuiceFS 在 AI 训练等高负载场景下的数据供给能力，可采用 MLPerf Storage 基准测试。该测试由 MLCommons 开发，重点衡量存储系统能否持续高效向计算侧提供数据。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;2.0 版本将测试分为训练负载和检查点负载两类，其中训练负载包括 3D U-Net、ResNet-50 和 CosmoFlow，三者在样本大小和访问特征上存在显著差异，并设置了最低 GPU 利用率要求：3D U-Net 与 ResNet-50 为 90%，CosmoFlow 为 70%。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153031649-1808809682.png&quot; class=&quot;ls-is-cached lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153031649-1808809682.png&quot; style=&quot;;padding: 0px;border: none;max-width: 800px;height: auto !important;cursor: zoom-in;transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;在测试流程中，数据首先从存储系统读入主机内存，再进入计算阶段。训练耗时由模拟方式复现，以模拟真实训练场景的数据流，从而无需实际部署 GPU，降低实验门槛并提升操作便利性。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153042630-939099216.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153042630-939099216.png&quot; style=&quot;;padding: 0px;border: none;max-width: 800px;height: auto !important;cursor: zoom-in;transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important&quot;/&gt;&lt;/p&gt;&lt;h2 id=&quot;03-mlperf-storage-v20-测试原理与调优&quot; style=&quot;margin: 20px 0px;padding: 0px;font-size: 21px;line-height: 1.5;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;03 MLPerf Storage v2.0 测试原理与调优&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;在介绍具体的模型测试结果之前，需要先了解分布式训练的数据访问原理，有助于读者明白 GPU 利用率、存储吞吐和性能瓶颈的成因，从而更好地理解后续的测试结果和调优策略。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;分布式机器学习通常采用数据并行方式，即多个并行进程共享同一数据集，每个进程分别负责读取和处理对应的训练批次。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153050871-91287406.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153050871-91287406.png&quot; style=&quot;;padding: 0px;border: none;max-width: 800px;height: auto !important;cursor: zoom-in;transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;MLPerf Storage 的训练测试也遵循这一思路，每个训练进程按批次从存储系统读取数据，并通过模拟计算来评估存储系统的持续供数能力。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153058596-1396909804.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153058596-1396909804.png&quot; style=&quot;;padding: 0px;border: none;max-width: 800px;height: auto !important;cursor: zoom-in;transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;为了理解测试中性能表现的来源，还需要理解 JuiceFS 客户端的数据处理链路。使用 JuiceFS 进行测试时，如图所示，其执行流程大致可分为三部分。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153105536-1335855624.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/2544292/202603/2544292-20260327153105536-1335855624.png&quot; style=&quot;;padding: 0px;border: none;max-width: 800px;height: auto !important;cursor: zoom-in;transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important&quot;/&gt;&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em;margin-left: 40px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;左侧：应用侧 I/O 线程，例如&amp;nbsp;&lt;code style=&quot;margin: 0px 3px;padding: 0px 5px;font-family: ui-monospace, SFMono-Regular, &amp;#39;SF Mono&amp;#39;, Menlo, Consolas, &amp;#39;Liberation Mono&amp;#39;, monospace, sans-serif;font-size: 12px;line-height: 1.8;display: inline-block;overflow-x: auto;vertical-align: middle;border-radius: 3px;color: rgb(192, 52, 29);background-color: rgba(0, 0, 0, 0.04);border: none !important&quot;&gt;fio&lt;/code&gt;&amp;nbsp;或 MLPerf Storage 的&amp;nbsp;&lt;code style=&quot;margin: 0px 3px;padding: 0px 5px;font-family: ui-monospace, SFMono-Regular, &amp;#39;SF Mono&amp;#39;, Menlo, Consolas, &amp;#39;Liberation Mono&amp;#39;, monospace, sans-serif;font-size: 12px;line-height: 1.8;display: inline-block;overflow-x: auto;vertical-align: middle;border-radius: 3px;color: rgb(192, 52, 29);background-color: rgba(0, 0, 0, 0.04);border: none !important&quot;&gt;DataLoader&lt;/code&gt;&amp;nbsp;线程，负责发起&amp;nbsp;&lt;code style=&quot;margin: 0px 3px;padding: 0px 5px;font-family: ui-monospace, SFMono-Regular, &amp;#39;SF Mono&amp;#39;, Menlo, Consolas, &amp;#39;Liberation Mono&amp;#39;, monospace, sans-serif;font-size: 12px;line-height: 1.8;display: inline-block;overflow-x: auto;vertical-align: middle;border-radius: 3px;color: rgb(192, 52, 29);background-color: rgba(0, 0, 0, 0.04);border: none !important&quot;&gt;read/write&lt;/code&gt;&amp;nbsp;请求并等待请求完成。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;中间：FUSE 守护进程中的请求处理主&amp;nbsp;&lt;code style=&quot;margin: 0px 3px;padding: 0px 5px;font-family: ui-monospace, SFMono-Regular, &amp;#39;SF Mono&amp;#39;, Menlo, Consolas, &amp;#39;Liberation Mono&amp;#39;, monospace, sans-serif;font-size: 12px;line-height: 1.8;display: inline-block;overflow-x: auto;vertical-align: middle;border-radius: 3px;color: rgb(192, 52, 29);background-color: rgba(0, 0, 0, 0.04);border: none !important&quot;&gt;goroutine&lt;/code&gt;，负责接收并处理来自内核态的 FUSE 请求，将文件数据放入内存缓冲区和缓存，并触发后端元数据与对象存储访问。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;右侧：Meta client 和 ObjectStore client 的异步&amp;nbsp;&lt;code style=&quot;margin: 0px 3px;padding: 0px 5px;font-family: ui-monospace, SFMono-Regular, &amp;#39;SF Mono&amp;#39;, Menlo, Consolas, &amp;#39;Liberation Mono&amp;#39;, monospace, sans-serif;font-size: 12px;line-height: 1.8;display: inline-block;overflow-x: auto;vertical-align: middle;border-radius: 3px;color: rgb(192, 52, 29);background-color: rgba(0, 0, 0, 0.04);border: none !important&quot;&gt;goroutine&lt;/code&gt;，负责与后端 MetaDB 和 ObjectStore 集群进行数据与元数据交互。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;从性能分析的角度看，这条链路需要重点关注两类问题。第一类是数据拷贝，对应图中的 2.1、3、4、5、6 等步骤，这些位置都会带来额外的内存复制开销，因此往往是分析延迟和 CPU 开销时的重点。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;第二类是同步与异步边界。从图中可以看出，1、2、3、4、5、6 这些步骤总体属于同步路径，也就是请求发起后，需要等待当前阶段完成才能继续向下推进；而 7 属于异步路径，由后台&amp;nbsp;&lt;code style=&quot;margin: 0px 3px;padding: 0px 5px;font-family: ui-monospace, SFMono-Regular, &amp;#39;SF Mono&amp;#39;, Menlo, Consolas, &amp;#39;Liberation Mono&amp;#39;, monospace, sans-serif;font-size: 12px;line-height: 1.8;display: inline-block;overflow-x: auto;vertical-align: middle;border-radius: 3px;color: rgb(192, 52, 29);background-color: rgba(0, 0, 0, 0.04);border: none !important&quot;&gt;goroutine&lt;/code&gt;&amp;nbsp;负责与后端存储交互。&lt;/p&gt;&lt;h3 id=&quot;测试-1unet-3d&quot; style=&quot;margin: 10px 0px;padding: 0px;font-size: 16px;line-height: 1.5;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;测试 1：Unet 3d&lt;/h3&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;在这个测试中，样本为 146 MiB 的图像文件，我们主要关注大块数据的读取性能。测试结果显示：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em;margin-left: 40px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;单机环境下最高可稳定运行 5 块 GPU，GPU 利用率约为 50%，&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;而双机场景可支持 10 块 GPU，GPU 利用率同样约为 50%。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;为了提升数据读取效率，对训练参数进行了优化：将&amp;nbsp;&lt;code style=&quot;margin: 0px 3px;padding: 0px 5px;font-family: ui-monospace, SFMono-Regular, &amp;#39;SF Mono&amp;#39;, Menlo, Consolas, &amp;#39;Liberation Mono&amp;#39;, monospace, sans-serif;font-size: 12px;line-height: 1.8;display: inline-block;overflow-x: auto;vertical-align: middle;border-radius: 3px;color: rgb(192, 52, 29);background-color: rgba(0, 0, 0, 0.04);border: none !important&quot;&gt;reader&lt;/code&gt;&amp;nbsp;并发线程数从 4 调整为 16，以加快数据生成速度，并将数据读取方式改为 direct I/O，以减少缓冲区和内存拷贝开销。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;&lt;strong style=&quot;;padding: 0px&quot;&gt;业务指标显示，当单机挂载 6 块 GPU 时，GPU 利用率仅为 83%，对应带宽约为 15.1 GB/s，未达到预期的高利用率目标&lt;/strong&gt;。进一步使用 FIO 对存储侧进行测试后发现，其带宽同样约为 15.1 GB/s，&lt;strong style=&quot;;padding: 0px&quot;&gt;说明此时系统瓶颈已经落在 JuiceFS 客户端带宽 上，而不是 GPU 计算侧本身&lt;/strong&gt;。&lt;/p&gt;&lt;h4 id=&quot;优化分析-1绑定-cpu&quot; style=&quot;margin: 10px 0px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;优化分析 1：绑定 CPU&lt;/h4&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;为了深入分析客户端带宽受限的原因，我们对进程进行了 CPU 绑定，将其固定在 CPU1（NUMA 2、3 节点）运行。通过工具观察，48 个 CPU 核心几乎全部占满，进一步分析 top-down、memory 和 miss 指标发现，系统表现出明显 Memory Bound，主要耗时集中在内存拷贝上。这说明，在 CPU 绑定场景下，JuiceFS 性能瓶颈主要来自 CPU 处理能力和跨 NUMA 节点内存拷贝带来的额外延迟。&lt;/p&gt;&lt;h4 id=&quot;优化分析-2-不进行-cpu-绑定&quot; style=&quot;margin: 10px 0px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;优化分析 2： 不进行 CPU 绑定&lt;/h4&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;为了理解系统在更通用条件下的带宽限制，我们进一步观察了不绑定 CPU 的情况。通过观察可以看到，CPU 并未被完全用满，但 devkit tuner numafast 指标显示，系统中的 remote 内存访问比例高达约 80%。这意味着，大量内存访问已经跨越本地 NUMA 节点，甚至可能跨越 CPU socket，从而引入了显著的带宽损失和访问时延。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;从硬件带宽特性看，跨片内存访问本身就存在明显限制。例如，在 Arm 平台上，跨 socket 的理论物理带宽约为 60 GB/s；进一步通过实测，跨片 copy 带宽在 Arm1 上约为 48 GB/s，而在两组 x86 平台上分别约为 37 GB/s 和 28 GB/s。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;这说明，在不绑定 CPU 的情况下，虽然计算核表面上没有被完全耗尽，但大量跨节点、跨 socket 的远端内存访问已经成为新的主要开销来源。因此，可以推测，此时 JuiceFS 带宽无法继续提升，很可能并不是单纯受限于 CPU 算力，而是受限于跨片内存访问的带宽与时延。&lt;strong style=&quot;;padding: 0px&quot;&gt;换言之，系统瓶颈已经从“本地 CPU 忙不过来”转移为“远端内存访问代价过高”&lt;/strong&gt;。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;综合来看，在两种场景下，JuiceFS 带宽无法提升的原因并不相同：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em;margin-left: 40px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;绑定 CPU 时，主要受限于 CPU 资源消耗以及大量内存拷贝带来的访问开销；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;不绑定 CPU 时，主要受限于高比例 非本地内存访问，尤其可能是跨 socket 访问带来的带宽和时延损失。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;测试-2resnet50&quot; style=&quot;margin: 10px 0px;padding: 0px;font-size: 16px;line-height: 1.5;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;测试 2：Resnet50&lt;/h3&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;ResNet-50 测试的单个样本较小，单个样本大小约为 150 KiB，每个 batch 包含 400 个样本，每个 batch 的总数据量约 58.5 MiB。本次 I/O 测试关注 GPU 高并发下的数据加载效率及训练吞吐。测试显示系统可在大规模 GPU 下维持较高利用率：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em;margin-left: 40px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;单机：50 块 GPU，GPU 利用率 95%，带宽约 9.2 GB/s&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;双机：96 块 GPU，GPU 利用率 90%，带宽约 16.9 GB/s&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;在测试过程中，我们将关键参数&amp;nbsp;&lt;code style=&quot;margin: 0px 3px;padding: 0px 5px;font-family: ui-monospace, SFMono-Regular, &amp;#39;SF Mono&amp;#39;, Menlo, Consolas, &amp;#39;Liberation Mono&amp;#39;, monospace, sans-serif;font-size: 12px;line-height: 1.8;display: inline-block;overflow-x: auto;vertical-align: middle;border-radius: 3px;color: rgb(192, 52, 29);background-color: rgba(0, 0, 0, 0.04);border: none !important&quot;&gt;reader.read_threads&lt;/code&gt;&amp;nbsp;从 8 调整为 1，对于该模型（中等大小的图像模型），单线程即可满足数据供给需求。&lt;/p&gt;&lt;h4 id=&quot;优化分析-1-单机性能瓶颈与内存带宽影响&quot; style=&quot;margin: 10px 0px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;优化分析 1： 单机性能瓶颈与内存带宽影响&lt;/h4&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;在单机配置 55 块 GPU 时，GPU 利用率下降至 86%，带宽仍为 9.2 GB/s，表明系统瓶颈已转移至 JuiceFS 客户端带宽。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;进一步分析发现，ResNet-50 测试采用 Buffer I/O 模式，除了读取数据外，处理数据集时的 内存拷贝会消耗一部分内存带宽。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;系统内存拷贝带宽受内存通道数、内存频率及 CPU 频率影响。通过对多台配置不同的机器进行 stream 测试，得到的单机顺序读带宽与系统内存带宽测得的可比带宽一致，&lt;strong style=&quot;;padding: 0px&quot;&gt;表明读数据吞吐能力在很大程度上取决于系统内存带宽。对于需要高吞吐、高 GPU 利用率的训练任务，建议优先选择内存带宽较高的机型，可显著提升数据供给能力和训练效率&lt;/strong&gt;。&lt;/p&gt;&lt;table&gt;&lt;thead style=&quot;;padding: 0px&quot;&gt;&lt;tr style=&quot;;padding: 0px&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;;padding: 8px 14px;background-color: rgb(250, 250, 250);border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px;text-align: left&quot;&gt;&lt;br/&gt;&lt;/th&gt;&lt;th style=&quot;;padding: 8px 14px;background-color: rgb(250, 250, 250);border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px;text-align: left&quot;&gt;单 CPU 内存拷贝带宽数据&lt;/th&gt;&lt;th style=&quot;;padding: 8px 14px;background-color: rgb(250, 250, 250);border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px;text-align: left&quot;&gt;JuiceFS 单机部署读带宽&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;;padding: 0px&quot;&gt;&lt;tr style=&quot;;padding: 0px&quot;&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;Arm3&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;Arm3: 171 GB/s&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;25.3 GiB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;;padding: 0px&quot;&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;Arm2&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;114 GB/s&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;21.6 GiB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;;padding: 0px&quot;&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;Arm1&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;106 GB/s&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;18.3 GiB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;;padding: 0px&quot;&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;x862&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;90 GB/s&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;17.9 GiB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;;padding: 0px&quot;&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;x861&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;82 GB/s&lt;/td&gt;&lt;td style=&quot;;padding: 8px 14px;border-color: rgb(192, 192, 192);border-collapse: collapse;min-width: 50px&quot;&gt;16.6 GiB/s&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h4 id=&quot;优化分析-2双机扩展瓶颈与分布式限制&quot; style=&quot;margin: 10px 0px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;优化分析 2：双机扩展瓶颈与分布式限制&lt;/h4&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;在多节点部署中，除了单机性能限制外，跨节点内存访问、网络传输和元数据延迟会成为新的瓶颈，因此在单机分析之后进行双机测试，有助于识别这些分布式约束并指导系统优化。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;在双机场景下，理论上可以支持 100 块 GPU，但实际测试中只能达到 96 块 GPU。通过分析发现，每个操作的读取延迟有所增加。尽管文件数据已缓存在本地盘上，元数据访问延迟仍然成为主要限制因素。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;为解决这一问题，对系统进行了多方面优化：&lt;/p&gt;&lt;ol style=&quot;margin-bottom: 1em;margin-left: 40px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;将 CPU 核心分组，保证训练线程与 I/O 线程在同一 NUMA 节点上运行。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;将纯数据处理和元数据访问分别分配到不同 CPU 核心和存储路径上。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;调整 Redis 缓存和本地缓存策略，减少高并发访问元数据时的延迟。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;经过上述调优后，双机场景能够稳定支撑 100 块 GPU 运行，GPU 利用率达到预期水平。&lt;/p&gt;&lt;h3 id=&quot;测试-3cosmoflow&quot; style=&quot;margin: 10px 0px;padding: 0px;font-size: 16px;line-height: 1.5;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;测试 3：cosmoflow&lt;/h3&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;与之前的模型相比，这个模型的单样本数据量更小，这也意味着对 I/O 和元数据访问的要求更高。在单机和双机场景下，CosmoFlow 测试显示：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em;margin-left: 40px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;单机：最高稳定 10 块 GPU（偶尔可撑到 12 块 GPU），GPU 利用率约 75%，带宽约 5.6 GB/s&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;关键参数调整：将&amp;nbsp;&lt;code style=&quot;margin: 0px 3px;padding: 0px 5px;font-family: ui-monospace, SFMono-Regular, &amp;#39;SF Mono&amp;#39;, Menlo, Consolas, &amp;#39;Liberation Mono&amp;#39;, monospace, sans-serif;font-size: 12px;line-height: 1.8;display: inline-block;overflow-x: auto;vertical-align: middle;border-radius: 3px;color: rgb(192, 52, 29);background-color: rgba(0, 0, 0, 0.04);border: none !important&quot;&gt;reader.read_threads&lt;/code&gt;&amp;nbsp;从 4 调整为 1，每次读取 batch 数据量为 2 MiB，单线程即可满足数据供给需求。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;优化分析-1单机瓶颈内存拷贝限制-gpu-利用率&quot; style=&quot;margin: 10px 0px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;优化分析 1：单机瓶颈：内存拷贝限制 GPU 利用率&lt;/h4&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;当尝试增加 GPU 数量超过 10 块时，发现 GPU 利用率下降。分析日志和性能数据后发现：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em;margin-left: 40px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;数据读取时间增加，而元数据访问延迟变化不大。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;文件数据已缓存在本地盘上，磁盘队列未满，延迟也不高，因此瓶颈不在存储设备。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;使用性能分析工具观察发现，关键瓶颈操作主要集中在 内存拷贝（memcopy），数据读取流程中多次拷贝操作的延迟累积，导致整体读取时间增加。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;由此推测，当系统使用更多内存带宽时，内存拷贝延迟成为限制读取性能和 GPU 利用率的主要因素。&lt;/p&gt;&lt;h4 id=&quot;优化分析-2双机瓶颈分布式同步与元数据延迟&quot; style=&quot;margin: 10px 0px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;优化分析 2：双机瓶颈：分布式同步与元数据延迟&lt;/h4&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;在双机场景下，尝试 20 块 GPU 时，第一轮测试 GPU 利用率明显偏低。进一步分析发现：&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 1em;margin-left: 40px;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;一台机器已开始训练，而另一台机器仍在进行 Dataset 预处理，包括读取文件列表和分片操作。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;由于 CosmoFlow 数据量较大，高索引文件的读取耗时较长，导致两台机器未能同步开始训练，第一轮 GPU 利用率下降。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;为解决该问题，在代码中加入同步机制，确保所有节点在开始训练前完成 Dataset 预处理。经过该调整后，双机测试能够稳定支撑 20 块 GPU，GPU 利用率达到预期水平。&lt;/p&gt;&lt;h2 id=&quot;04-总结&quot; style=&quot;margin: 20px 0px;padding: 0px;font-size: 21px;line-height: 1.5;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;04 总结&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;首先，MLPerf Storage 通过不同样本、文件和 batch 大小的组合，考察文件系统的各项能力，包括大中小块顺序读能力、文件并发性能、总读带宽、元数据访问时延、文件读取时延以及文件操作的稳定性。在只读文件场景下，充分利用高速近端缓存（包括原数据和元数据缓存）可以显著提升读取性能。需要注意，文件越小，对 IOPS 和延迟的要求越高。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;其次，我们发现系统的内存和带宽对性能影响显著。在 Memory copy 密集型的应用中，内存拷贝不仅消耗内存带宽，同时也占用 CPU，表面上会出现“CPU 忙”的假象，实际上 CPU 大部分时间是在等待数据。测试结果显示，系统内存带宽对 JuiceFS 的吞吐能力有决定性影响，这也为选择服务器提供了参考标准：内存带宽越高的系统，其存储吞吐性能也越好。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;第三，Go 运行时对 NUMA 的感知有限，对于大规模 CPU 核心运行场景，性能可能不如小规模核心运行。对于多 NUMA 系统，应尽量避免跨 NUMA，尤其是跨 CPU socket 的访问，因为跨 socket 内存带宽通常较低（约几十 GB/s），会增加延迟并影响整体性能。因此，实际部署时只需要分配足够的 CPU 核心即可，无需过度使用全部核心，以避免额外的内存访问延迟。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;第四，在系统层面还有一些潜在优化点。例如，对于 Memory copy 密集的操作，部分 Arm 新系统提供了针对内存访问的指令优化，我们与 Arm 社区合作，将配置提升推送到社区中，新系统可以显著提升内存拷贝效率，在部分场景中带宽提升可达数十个百分点。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;此外，对于涉及大量内核与用户态交互的操作，例如文件读写和元数据处理，可以通过优化用户态与内核态的交互，减少不必要的调用次数，从而降低延迟。实践中也发现，将文件处理尽量集中在同一生产节点内，避免跨 NUMA 或跨 socket 的访问，可以进一步提升性能和稳定性。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto;padding: 0px;color: rgb(51, 51, 51);font-family: &amp;#39;PingFang SC&amp;#39;, &amp;#39;Microsoft YaHei&amp;#39;, &amp;#39;Helvetica Neue&amp;#39;, Helvetica, Arial, sans-serif;text-wrap-mode: wrap;background-color: rgb(255, 255, 255)&quot;&gt;最后，系统配置优化也体现在缓存策略上。例如，在单机高负载场景下，通过调整 JuiceFS 的内存缓存策略，减少无效内存带宽占用，可以有效提高 GPU 利用率和存储吞吐。整体来看，MLPerf Storage Benchmark 是一个系统工程，需要文件系统、内存带宽、CPU 调度和缓存策略等多方面配合，才能达到最优性能。&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Tue, 03 Mar 2026 16:19:10 +0800</pubDate></item><item><title>访问一个网站时遇到“404 Not Found”错误 </title><link>https://www.60002.cn/?id=4</link><description>&lt;p style=&quot;margin: 10px auto; padding: 0px; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;在。以下是一些常见的解决方法：&lt;/p&gt;&lt;h3 style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;检查URL&lt;/h3&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;确保URL正确&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;仔细检查URL，确保没有拼写错误或多余的字符。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;确认URL中的大小写是否正确，因为某些服务器对大小写敏感。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3 style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;刷新页面&lt;/h3&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;刷新页面&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;有时候问题可能是暂时的，尝试刷新页面（F5键或点击浏览器的刷新按钮）。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3 style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;清除浏览器缓存&lt;/h3&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;清除缓存和Cookies&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;浏览器缓存可能会导致旧的或错误的页面显示。清除浏览器缓存和Cookies，然后重新加载页面。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3 style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;检查网站状态&lt;/h3&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;确认网站是否正常运行&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;使用在线工具（如Down for Everyone or Just Me）检查网站是否对其他用户也显示404错误。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;查看网站的状态页面或社交媒体账号，了解是否有维护通知。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h3 style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;联系网站管理员&lt;/h3&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;联系网站管理员&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;如果上述方法都无法解决问题，可能是网站本身的问题。联系网站的技术支持或管理员寻求帮助。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Thu, 19 Feb 2026 16:16:24 +0800</pubDate></item><item><title>ERROR 1045 (28000): Access denied for user ‘root’@‘localhost’ (using password: NO) </title><link>https://www.60002.cn/?id=3</link><description>&lt;h3 style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;错误分析&lt;/h3&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;错误代码&lt;/strong&gt;: 1045&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;错误信息&lt;/strong&gt;: Access denied for user &amp;#39;root&amp;#39;@&amp;#39;localhost&amp;#39; (using password: NO)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;问题类型&lt;/strong&gt;: 数据库连接问题&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;可能的原因&lt;/h3&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;未提供密码&lt;/strong&gt;: 尝试连接数据库时没有提供密码。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;密码错误&lt;/strong&gt;: 提供了错误的密码。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;用户权限问题&lt;/strong&gt;: 用户&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;root&lt;/code&gt;&amp;nbsp;没有权限从&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;localhost&lt;/code&gt;&amp;nbsp;连接数据库。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;解决方案&lt;/h3&gt;&lt;ol style=&quot;margin-left: 2.5rem; padding: 0px; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Verdana, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px;&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;检查密码&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;确认是否提供了正确的密码。如果不确定密码，可以尝试重置&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;root&lt;/code&gt;&amp;nbsp;用户的密码。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px;&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;重置密码&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;使用以下命令重置&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;root&lt;/code&gt;&amp;nbsp;用户的密码（以 MySQL 为例）：&lt;/p&gt;&lt;div class=&quot;answer-code-wrap&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header-left&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;pre class=&quot;language-armasm highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto;&quot;&gt;sudo&amp;nbsp;mysql&amp;nbsp;-u&amp;nbsp;root&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在 MySQL 提示符下执行：&lt;/p&gt;&lt;div class=&quot;answer-code-wrap&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header-left&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;pre class=&quot;language-armasm highlighter-hljs&quot; highlighted=&quot;true&quot; has-selection=&quot;true&quot; style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto;&quot;&gt;ALTER&amp;nbsp;USER&amp;nbsp;&amp;#39;root&amp;#39;@&amp;#39;localhost&amp;#39;&amp;nbsp;IDENTIFIED&amp;nbsp;BY&amp;nbsp;&amp;#39;新密码&amp;#39;;FLUSH&amp;nbsp;PRIVILEGES;EXIT;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px;&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;检查用户权限&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;登录到 MySQL 并检查&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;root&lt;/code&gt;&amp;nbsp;用户的权限：&lt;/p&gt;&lt;div class=&quot;answer-code-wrap&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header-left&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;pre class=&quot;language-armasm highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto;&quot;&gt;sudo&amp;nbsp;mysql&amp;nbsp;-u&amp;nbsp;root&amp;nbsp;-p&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在 MySQL 提示符下执行：&lt;/p&gt;&lt;div class=&quot;answer-code-wrap&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header-left&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;pre class=&quot;language-armasm highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto;&quot;&gt;SELECT&amp;nbsp;User,&amp;nbsp;Host&amp;nbsp;FROM&amp;nbsp;mysql.user;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;确认&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;root&lt;/code&gt;&amp;nbsp;用户是否有从&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;localhost&lt;/code&gt;&amp;nbsp;连接的权限。如果没有，可以添加权限：&lt;/p&gt;&lt;div class=&quot;answer-code-wrap&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;answer-code-wrap-header-left&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;pre class=&quot;language-armasm highlighter-hljs&quot; highlighted=&quot;true&quot; has-selection=&quot;true&quot; style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto;&quot;&gt;GRANT&amp;nbsp;ALL&amp;nbsp;PRIVILEGES&amp;nbsp;ON&amp;nbsp;*.*&amp;nbsp;TO&amp;nbsp;&amp;#39;root&amp;#39;@&amp;#39;localhost&amp;#39;&amp;nbsp;WITH&amp;nbsp;GRANT&amp;nbsp;OPTION;FLUSH&amp;nbsp;PRIVILEGES;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px;&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;配置文件检查&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;检查 MySQL 配置文件（通常是&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;my.cnf&lt;/code&gt;&amp;nbsp;或&amp;nbsp;&lt;code style=&quot;margin: 0px 3px; padding: 0px 5px; font-family: ui-monospace, SFMono-Regular, &amp;quot;SF Mono&amp;quot;, Menlo, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace, sans-serif; font-size: 12px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border-radius: 3px; color: rgb(192, 52, 29); background-color: rgba(0, 0, 0, 0.04); border: none !important;&quot;&gt;my.ini&lt;/code&gt;），确保没有配置错误的用户或密码。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Thu, 22 Jan 2026 16:15:53 +0800</pubDate></item><item><title>Spring Cloud进阶--分布式权限校验OAuth2</title><link>https://www.60002.cn/?id=6</link><description>&lt;h1 id=&quot;分布式权限校验&quot; style=&quot;margin: 10px 0px; padding: 0px; line-height: 1.5; font-size: 28px; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;分布式权限校验&lt;/h1&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;现在有一个登录问题，假如需要用户登录之后才能查询图书和借阅图书。那要怎么设计？&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;单体应用的权限校验原理：&lt;/p&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;浏览器向服务端发送请求，访问网站&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;服务端接收请求后，创建一个sessionid，存储在服务端，然后发送给浏览器作为Cookie保存&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;以后浏览器每次请求都携带这个cookie。这样服务端根据cookie中的sessionid判断是哪个用户。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;但是分布式系统，各个微服务独立部署，用户登录了用户服务后，借阅服务和图书服务会知道用户登录了吗？&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183506830-1575582278.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183506830-1575582278.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;用户登录后，session中的用户数据保存在用户服务中，其他服务没有对应信息，按怎么能让其他服务获取这些信息呢，实现服务间的session同步呢？&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;将session移出服务器，统一存放！比如存到redis或者MySQL，这样就能保证所有服务获得session。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;具体的实现步骤如下：&lt;/p&gt;&lt;ol style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px;&quot;&gt;为每个服务引入依赖：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;);&quot;&gt;&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.session&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-session-data-redis&amp;lt;/artifactId&amp;gt;&amp;lt;/dependency&amp;gt;&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-boot-starter-data-redis&amp;lt;/artifactId&amp;gt;&amp;lt;/dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-boot-starter-security&amp;lt;/artifactId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px;&quot;&gt;修改每个服务配置文件：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin-top: 0px; margin-bottom: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;);&quot;&gt;spring:
&amp;nbsp;&amp;nbsp;session:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;存储类型修改为redis
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;store-type:&amp;nbsp;redis
&amp;nbsp;&amp;nbsp;redis:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;redis&amp;nbsp;服务器信息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;host:&amp;nbsp;localhost&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这样设置之后，每个服务只有在登录成功后才能访问！&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;只要在一个服务登录成功，其他服务就会直接调用，不用重复登录！&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;注意，如果是服务A 调用服务B，用户在服务B登录，然后访问服务A。那么访问是失败的！&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;因为服务A没有验证，请求没有携带有效cookie，验证失败，导致其无法访问服务B。&lt;/p&gt;&lt;h1 id=&quot;oauth-20-实现单点登录&quot; style=&quot;margin: 10px 0px; padding: 0px; line-height: 1.5; font-size: 28px; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;OAuth 2.0 实现单点登录&lt;/h1&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;上面虽然解决了session共享问题，但是由于每个服务都有自己的验证模块，导致整个系统存在冗余功能，那么能否实现只有一个服务进行登录，然后可以访问其他的服务呢？&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;单点登录正好解决这一问题！&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;一些常见的第三方登录就是使用这种方式：比如淘宝和咸鱼可以使用支付宝账号登录，虽然他们属于三个不同的应用系统，需要获取支付宝用户信息并授权给其他应用。就要使用OAuth 2.0实现第三方授权。那么到底是怎么实现的呢？&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;OAuth 2.0一共有四种授权模式：&lt;/p&gt;&lt;ol style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px;&quot;&gt;客户端模式：最简单的一种模式。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px;&quot;&gt;这里的客户端可以是web、App、小程序或者第三方服务&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;先向验证服务器请求获取一个token（令牌）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;拿到令牌后去访问对应的资源（比如借阅信息，这样资源服务器才能知道访问者是谁以及是否登录成功）&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无标2题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183519326-1364045640.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183519326-1364045640.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;这种模式比较简单，但是失去了用户验证的意义，压根就不是给用户校验准备的，更适合服务内部调用的场景！&lt;/strong&gt;&lt;/p&gt;&lt;ol start=&quot;2&quot; style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;密码模式：相比客户端模式，多了用户名和密码信息，用户需要提供用户名和密码才能获取到token&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无标3题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183526395-1091054403.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183526395-1091054403.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;这种模式有一个缺点：会直接将账号密码信息泄露给客户端（或者第三方应用），这样风险很大，一般不会使用这种模式！&lt;/strong&gt;&lt;/p&gt;&lt;ol start=&quot;3&quot; style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;隐式授权模式：用户访问服务时，会重定向到认证服务器，认证服务器返回用户一个认证页面，等待用户授权，用户填写信息完成授权后，认证服务器返回token。用户再携带token去访问服务。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无标4题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183535736-157791579.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183535736-157791579.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;这种模式适合没有服务端的第三方应用页面，验证都是在验证服务器进行，不会泄露敏感信息，但是依然存在泄露token的风险！&lt;/strong&gt;&lt;/p&gt;&lt;ol start=&quot;4&quot; style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;授权码模式：最安全的一种模式，也是推荐使用的模式，手机上很多APP都是使用这种模式！&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这种模式不会直接返回token，而是返回授权码，真正的token时通过应用服务器访问验证服务器获取的。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;首先应用服务器和验证服务器会共享一个secret，验证服务器在用户完成验证后返回应用服务器一个授权码。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;应用服务器将授权码和secret一起交给验证服务器，来生成token，并返回给应用服务器。token一直在服务器之间流转，不会直接给到客户端。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无5标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183543906-1677229417.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183543906-1677229417.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;就算有人获取到授权码也没用，因为没有secret，就没法获取token。并且token不会返回给客户端，所以减少了泄露的风险！&lt;/strong&gt;&lt;/p&gt;&lt;h2 id=&quot;搭建验证服务器&quot; style=&quot;margin: 10px 0px; padding: 0px; line-height: 1.5; font-size: 21px; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;搭建验证服务器&lt;/h2&gt;&lt;ol style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;使用Spring官方提供的验证服务器，先在父项目中加入Spring Cloud依赖：&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-cloud-dependencies&amp;lt;/artifactId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;version&amp;gt;2021.0.1&amp;lt;/version&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;type&amp;gt;pom&amp;lt;/type&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;scope&amp;gt;import&amp;lt;/scope&amp;gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;ol start=&quot;2&quot; style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;新建一个auth-service子模块，并引入依赖：&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-boot-starter-web&amp;lt;/artifactId&amp;gt;&amp;lt;/dependency&amp;gt;&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-boot-starter-security&amp;lt;/artifactId&amp;gt;&amp;lt;/dependency&amp;gt;&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-cloud-starter-oauth2&amp;lt;/artifactId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;version&amp;gt;2.2.5.RELEASE&amp;lt;/version&amp;gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;ol start=&quot;3&quot; style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;添加配置文件：&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;server:
&amp;nbsp;&amp;nbsp;port:&amp;nbsp;8500
&amp;nbsp;&amp;nbsp;servlet:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#为了防止一会在服务之间跳转导致Cookie打架，（因为所有服务都是localhost，都会存JSESSIONID）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#这里修改以下&amp;nbsp;context-path，保证Cookie会使用指定路径，就不会和其他服务打架了
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;这样Cookie就会存放在localhost:8500/sso/**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;注意：之后的请求都得加上这个路径
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;context-path:&amp;nbsp;/sso&lt;/pre&gt;&lt;ol start=&quot;4&quot; style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;编写配置类（OAuth2的配置类和Spring Security的配置类）：&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; has-selection=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Configurationpublic&amp;nbsp;class&amp;nbsp;SecurityConfiguration&amp;nbsp;extends&amp;nbsp;WebSecurityConfigurerAdapter&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;void&amp;nbsp;configure(AuthenticationManagerBuilder&amp;nbsp;auth)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BCryptPasswordEncoder&amp;nbsp;encoder&amp;nbsp;=&amp;nbsp;new&amp;nbsp;BCryptPasswordEncoder();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auth.inMemoryAuthentication()&amp;nbsp;//&amp;nbsp;直接创建一个用户
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.passwordEncoder(encoder)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.withUser(&amp;quot;test&amp;quot;).password(encoder.encode(&amp;quot;123456&amp;quot;)).roles(&amp;quot;USER&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Bean&amp;nbsp;//加入容器管理，在Oauth配置中使用
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;AuthenticationManager&amp;nbsp;authenticationManagerBean()&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;super.authenticationManager();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;void&amp;nbsp;configure(HttpSecurity&amp;nbsp;http)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http.authorizeRequests()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.anyRequest().authenticated()&amp;nbsp;//&amp;nbsp;通过认证了才可以去访问
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.and()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.formLogin().permitAll();&amp;nbsp;//&amp;nbsp;放开表单登录权限
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; has-selection=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Configuration@EnableAuthorizationServer&amp;nbsp;//&amp;nbsp;开启验证服务器public&amp;nbsp;class&amp;nbsp;OAuth2Configuration&amp;nbsp;extends&amp;nbsp;AuthorizationServerConfigurerAdapter&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;AuthenticationManager&amp;nbsp;authenticationManager;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;final&amp;nbsp;BCryptPasswordEncoder&amp;nbsp;passwordEncoder&amp;nbsp;=&amp;nbsp;new&amp;nbsp;BCryptPasswordEncoder();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/*这个方式是对客户端进行配置，一个验证服务器可以预设很多个客户端
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;指定的客户端可以按照下面指定的方式进行验证
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;clients&amp;nbsp;客户端配置工具
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;*/
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;configure(ClientDetailsServiceConfigurer&amp;nbsp;clients)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clients.inMemory()//&amp;nbsp;直接硬编码创建，也可以从数据库取
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.withClient(&amp;quot;web&amp;quot;)&amp;nbsp;//&amp;nbsp;客户端名称
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.secret(passwordEncoder.encode(&amp;quot;654321&amp;quot;))&amp;nbsp;//&amp;nbsp;secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.autoApprove(false)&amp;nbsp;//&amp;nbsp;自动审批，暂时关闭
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.scopes(&amp;quot;book&amp;quot;,&amp;nbsp;&amp;quot;user&amp;quot;,&amp;quot;borrow&amp;quot;)&amp;nbsp;//&amp;nbsp;授权范围
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;5种授权模式
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.authorizedGrantTypes(&amp;quot;client_credentials&amp;quot;,&amp;quot;password&amp;quot;,&amp;quot;implicit&amp;quot;,&amp;quot;authorization_code&amp;quot;,&amp;nbsp;&amp;quot;refresh_token&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;configure(AuthorizationServerSecurityConfigurer&amp;nbsp;security)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;security.passwordEncoder(passwordEncoder)&amp;nbsp;//&amp;nbsp;设置编码器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.allowFormAuthenticationForClients()&amp;nbsp;//&amp;nbsp;允许客户端使用表单验证。一会我们的post请求中会携带表单信息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.checkTokenAccess(&amp;quot;permitAll()&amp;quot;);&amp;nbsp;//&amp;nbsp;允许所有的token查询请求
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;configure(AuthorizationServerEndpointsConfigurer&amp;nbsp;endpoints)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;endpoints.authenticationManager(authenticationManager);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;设置完后就可以启动服务了。然后可以用PostMan测试接口。&lt;/p&gt;&lt;h3 id=&quot;测试客户端模式&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;测试客户端模式&lt;/h3&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;客户端模式只要提供id和secret就可以能拿到token，注意要加一个grant_type指明授权方式，默认请求路径是http://localhost:8500/sso/oauth/token&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无6标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183558735-949122575.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183558735-949122575.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;发送请求后，我们得到的token是以json格式返回给我们&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无7标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183617555-836326011.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183617555-836326011.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;还可以访问http://localhost:8500/sso/oauth/check_token来验证我们的token是否有效：&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无8标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183606280-620281314.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183606280-620281314.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;h3 id=&quot;测试password模式&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;测试password模式&lt;/h3&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无标9题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183636788-1356621812.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183636788-1356621812.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;然后在请求头中添加Basic信息，之后发送请求就能获取到token&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无标10题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183643546-1590322003.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183643546-1590322003.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;h3 id=&quot;测试隐式授权模式&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;测试隐式授权模式&lt;/h3&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;1.现在验证服务器上进行登录操作，而不是直接请求token。验证登录请求地址：&lt;a href=&quot;http://localhost:8500/sso/oauth/authorize?client_id=web&amp;response_type=token&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow&quot; style=&quot;margin: 0px; padding: 0px; text-decoration-line: none; color: rgb(0, 0, 0); border-bottom: 1px dotted rgb(51, 51, 51);&quot;&gt;http://localhost:8500/sso/oauth/authorize?client_id=web&amp;amp;response_type=token&lt;/a&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;注意response_type=token 必须！&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无标11题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183652889-578037944.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183652889-578037944.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;输入用户名：test 密码：123456，然后登录&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无标12题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183659189-1282797254.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183659189-1282797254.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这时因为登录成功后，验证服务器要将结果返回给客户端，需要一个回调地址，这里需要在OAuth2的配置类里面配置&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; has-selection=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Overridepublic&amp;nbsp;void&amp;nbsp;configure(ClientDetailsServiceConfigurer&amp;nbsp;clients)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clients.inMemory()//&amp;nbsp;直接硬编码创建
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.withClient(&amp;quot;web&amp;quot;)&amp;nbsp;//&amp;nbsp;客户端名称
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.secret(passwordEncoder.encode(&amp;quot;654321&amp;quot;))&amp;nbsp;//&amp;nbsp;secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.autoApprove(false)&amp;nbsp;//&amp;nbsp;自动审批，暂时关闭
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.scopes(&amp;quot;book&amp;quot;,&amp;nbsp;&amp;quot;user&amp;quot;,&amp;quot;borrow&amp;quot;)&amp;nbsp;//&amp;nbsp;授权范围
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;可以写多个，当有多个时。需要在验证请求时指定使用哪个地址进行回调
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.redirectUris(&amp;quot;http://localhost:8201/login&amp;quot;)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;5种授权模式
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.authorizedGrantTypes(&amp;quot;client_credentials&amp;quot;,&amp;quot;password&amp;quot;,&amp;quot;implicit&amp;quot;,&amp;quot;authorization_code&amp;quot;,&amp;nbsp;&amp;quot;refresh_token&amp;quot;);
}&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;设置好，重新启动服务，然后登录页面，&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无13标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183707301-524393930.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183707301-524393930.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;会自动请求重定向的地址，并且携带了token&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无14标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183714136-2114489292.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183714136-2114489292.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;h3 id=&quot;测试授权码模式&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;测试授权码模式&lt;/h3&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;流程和上面的一致，但是请求类型时code类型，请求地址是：&lt;a href=&quot;http://localhost:8500/sso/oauth/authorize?client_id=web&amp;response_type=code&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow&quot; style=&quot;margin: 0px; padding: 0px; text-decoration-line: none; color: rgb(0, 0, 0); border-bottom: 1px dotted rgb(51, 51, 51);&quot;&gt;http://localhost:8500/sso/oauth/authorize?client_id=web&amp;amp;response_type=code&lt;/a&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这时能获取到授权码：amXZxw&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;然后使用postMan 进行获取token&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无15标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183722339-1876696291.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183722339-1876696291.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;h3 id=&quot;刷新token&quot; style=&quot;margin: 10px 0px; padding: 0px; font-size: 16px; line-height: 1.5; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;刷新token&lt;/h3&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;当token过期时，可以使用refresh_token 来获取新token&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无16标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183729996-1470765641.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183729996-1470765641.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这里返回报错了，查看日志发现需要我们单独配置一个UserDetailService，我们在SpringSecurity的配置类中 加入如下代码：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Override@Beanpublic&amp;nbsp;UserDetailsService&amp;nbsp;userDetailsServiceBean()&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;super.userDetailsServiceBean();
}&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;然后在OAuth2的配置类中的endpoints设置方法中修改代码如下：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Autowiredprivate&amp;nbsp;UserDetailsService&amp;nbsp;userDetailsService;@Overridepublic&amp;nbsp;void&amp;nbsp;configure(AuthorizationServerEndpointsConfigurer&amp;nbsp;endpoints)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;endpoints.authenticationManager(authenticationManager)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.userDetailsService(userDetailsService);
}&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;然后重启服务器，再重新测试就能获取到新token&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;注意：refresh_token参数的值，是获取token时返回的refresh_token值，不是token值！&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无17标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183739488-966227715.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183739488-966227715.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;h2 id=&quot;基于enableoauth2sso实现单点登录&quot; style=&quot;margin: 10px 0px; padding: 0px; line-height: 1.5; font-size: 21px; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;基于@EnableOAuth2Sso实现单点登录&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;前面已经搭建了验证服务器，SpringCloud为我们提供了客户端的直接实现，我们只需要加一个注解和少量配置就可以将服务作为一个单点登录应用，使用的是&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;授权码模式&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;也就是说，这种模式只是将验证方式由默认登录形式改成统一在授权服务器登录！&lt;/p&gt;&lt;ol style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;先引入依赖&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-boot-starter-security&amp;lt;/artifactId&amp;gt;&amp;lt;/dependency&amp;gt;&amp;lt;dependency&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artifactId&amp;gt;spring-cloud-starter-oauth2&amp;lt;/artifactId&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;version&amp;gt;2.2.5.RELEASE&amp;lt;/version&amp;gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;ol start=&quot;2&quot; style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;在微服务的启动类上加@EnableOAuth2Sso注解&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;添加配置信息&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; has-selection=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;security:
&amp;nbsp;&amp;nbsp;oauth2:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client-id:&amp;nbsp;web
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client-secret:&amp;nbsp;654321
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;获取token地址
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;access-token-uri:&amp;nbsp;http://localhost:8500/sso/oauth/token
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;验证页面地址
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;user-authorization-uri:&amp;nbsp;http://localhost:8500/sso/oauth/authorize
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resource:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;token信息获取和校验地址
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;token-info-uri:&amp;nbsp;http://localhost:8500/sso/oauth/check_token&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;然后启动服务，就完成了单点登录验证！&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这里把另外2种服务的重定向地址也加上，各自服务的依赖、配置、注解加上后启动。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这样只要在验证服务器登录，只要登陆过，就可以访问这三个服务了。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;但是有个问题，由于session不同步，每次访问不同的服务都会重新去验证服务器验证一次。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这里有2个解决方案：&lt;/p&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;和之前一样做session统一存储&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;设置context-path路径，每个服务单独设置&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;但是这样依然没法解决服务间调用问题，所以仅依靠单点登录的模式不行。&lt;/p&gt;&lt;h2 id=&quot;基于enableresourceserver实现&quot; style=&quot;margin: 10px 0px; padding: 0px; line-height: 1.5; font-size: 21px; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;基于@EnableResourceServer实现&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;上一种方式是将我们的服务当作单点应用直接实现单点登录，那如果是以第三方应用进行访问呢？&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这时需要将我们的服务作为资源服务，作为资源服务就不会再提供验证过程，而是直接&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;要求对方请求时携带token就可以。&lt;/strong&gt;&lt;/p&gt;&lt;ol style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;给启动类添加注解@EnableResourceServer&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;添加配置&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;security:
&amp;nbsp;&amp;nbsp;oauth2:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client-id:&amp;nbsp;web
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client-secret:&amp;nbsp;654321
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resource:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;token信息获取和校验地址，用于资源服务器验证你这个token是否能访问我这个服务以及用户信息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;token-info-uri:&amp;nbsp;http://localhost:8500/sso/oauth/check_token&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;然后启动服务，这时直接访问会显示未授权，需要先通过密码模式获取一个token，&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;第一种方式：在访问地址上加上access_token 参数就可以访问了&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;比如这样访问：&lt;a href=&quot;http://localhost:8201/book/1?access_token=ef08a607-568e-4b50-b50d-e9614c97b83c&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow&quot; style=&quot;margin: 0px; padding: 0px; text-decoration-line: none; color: rgb(0, 0, 0); border-bottom: 1px dotted rgb(51, 51, 51);&quot;&gt;localhost:8201/book/1?access_token=ef08a607-568e-4b50-b50d-e9614c97b83c&lt;/a&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;第二种方式，在请求头种添加‘Authorization’,值为Bearer+一个空格+Token值：&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无18标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183754596-948613572.png&quot; class=&quot;ls-is-cached lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183754596-948613572.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这样资源服务器就搭建完成了，那如何对资源服务器进行自定义，希望某个用户授权了指定的Scope才可以访问此服务？&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;需要给资源服务编写一个配置类：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Configurationpublic&amp;nbsp;class&amp;nbsp;ResourceConfiguration&amp;nbsp;extends&amp;nbsp;ResourceServerConfigurerAdapter&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;void&amp;nbsp;configure(HttpSecurity&amp;nbsp;http)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http.authorizeRequests().anyRequest()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;添加Scope&amp;nbsp;规则。token必须有这个scope才可以访问我
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.access(&amp;quot;#oauth2.hasScope(&amp;#39;book&amp;#39;)&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;由此可见，资源服务器不必再将Security信息保存再session种了，只需要拿到token去验证服务器，就可以获得用户信息，不需要使用之前的session存储机制了。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;那如何在使用RestTemplate 服务间调用时，加上token呢？&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;可以直接使用OAuth2RestTemplate,它会在请求时携带token。它继承自RestTemplate ，这里直接定义个Bean&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Configurationpublic&amp;nbsp;class&amp;nbsp;BeanConfiguration&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OAuth2ClientContext&amp;nbsp;oauth2ClientContext;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Bean
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;负载均衡
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//@LoadBalanced
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;OAuth2RestTemplate&amp;nbsp;restTemplate()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;new&amp;nbsp;OAuth2RestTemplate(new&amp;nbsp;ClientCredentialsResourceDetails(),oauth2ClientContext);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;具体的调用代码如下：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; has-selection=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Servicepublic&amp;nbsp;class&amp;nbsp;BorrowServiceImpl&amp;nbsp;implements&amp;nbsp;BorrowService&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;BorrowMapper&amp;nbsp;borrowMapper;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;OAuth2RestTemplate&amp;nbsp;restTemplate;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;BorrowDetail&amp;nbsp;findBorrowById(int&amp;nbsp;uid)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;List&amp;lt;Borrow&amp;gt;&amp;nbsp;allByUid&amp;nbsp;=&amp;nbsp;borrowMapper.getAllByUid(uid);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;获取用户信息&amp;nbsp;localhost:8101&amp;nbsp;改成服务名user-service
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;User&amp;nbsp;user&amp;nbsp;=&amp;nbsp;restTemplate.getForObject(&amp;quot;http://user-service/user/&amp;quot;&amp;nbsp;+&amp;nbsp;uid,&amp;nbsp;User.class);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;获取每本书的详细信息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;List&amp;lt;Book&amp;gt;&amp;nbsp;bookList&amp;nbsp;=&amp;nbsp;allByUid.stream().map(borrow&amp;nbsp;-&amp;gt;&amp;nbsp;restTemplate.getForObject(&amp;quot;http://book-service/book/&amp;quot;&amp;nbsp;+&amp;nbsp;borrow.getBid(),&amp;nbsp;Book.class))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.collect(Collectors.toList());&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;new&amp;nbsp;BorrowDetail(user,&amp;nbsp;bookList);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;那使用OpenFeign时，怎么加上token呢？&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;只需要加上相应的配置就可以了：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;feign:
&amp;nbsp;&amp;nbsp;oauth2:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;开启&amp;nbsp;oauth2支持，这样就会在请求头中加token了
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;enabled:&amp;nbsp;true
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;同时开启负载均衡支持
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;load-balanced:&amp;nbsp;true&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;总结：&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;作为资源服务器和作为客户端时不同的！&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;虽然都是拿到token然后去验证服务器进行验证，然而&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;客户端拿到的token验证成功后，还是要保存session信息，相当于只是将登录流程换到统一的验证服务器上进行罢了&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;资源服务器，是由客户端进行登录验证，然后再携带token进行访问，这种模式是常见的模式！&lt;/p&gt;&lt;h2 id=&quot;使用jwt存储token&quot; style=&quot;margin: 10px 0px; padding: 0px; line-height: 1.5; font-size: 21px; font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;使用jwt存储token&lt;/h2&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;由于每次访问资源服务器时，资源服务器由于不知道用户信息，每次都需要请求验证服务器来获取用户信息，这样在大量请求下，验证服务器的压力会非常大。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;而jwt就是解决了这个问题，使用jwt之后，token中会直接保存用户信息，这样资源服务器就不用每次都询问验证服务器了，自行解析就可以了。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;jwt（json web token），它定义了一种紧凑和自成一体的方式，用于再各方之间作为json对象安全地传输信息。因为采用了数字签名，所以当被篡改后，服务器可以快速发现。jwt可以使用密钥（HMAC算法）或者RSA或ECDSA进行公钥/私钥对进行签名。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无标20题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183847315-484893921.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183847315-484893921.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;jwt令牌由3部分组成：标头（Header）、有效载荷（Payload）、签名（Signature）。传输时，会将jwt的3部分分别进行base64编码后使用小数点连接形成最终的字符串。&lt;/p&gt;&lt;ul style=&quot;margin-left: 2.5rem; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;标头：包含一些元数据信息，比如jwt签名所使用的加密算法、类型，这里统一都是JWT&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;有效载荷：包括用户名称、令牌发放时间、过期时间、jwtID等，也可以自定义添加字段，这里一般存放用户信息&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;签名：首先指定一个密钥，该密钥只保存在服务器中，用户无法获取。然后使用Header中指定的算法对Header和Payload进行base64编码，编码结果通过密钥计算哈希值，这个哈希值就是签名，这个签名会用于之后验证内容是否被篡改。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这样就可以使用jwt处理token了。&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;客户端&lt;/strong&gt;-----请求token--&amp;gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;验证服务器&lt;/strong&gt;-----返回jwt令牌-----&amp;gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;客户端&lt;/strong&gt;---携带jwt令牌---&amp;gt;&lt;strong style=&quot;margin: 0px; padding: 0px;&quot;&gt;资源服务器&lt;/strong&gt;------自己解析jwt，根据签名信息自行校验----&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这里使用对称密钥进行签名。在验证服务中的Security配置类中加入如下代码：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Beanpublic&amp;nbsp;JwtAccessTokenConverter&amp;nbsp;tokenConverter()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;JwtAccessTokenConverter&amp;nbsp;jwtAccessTokenConverter&amp;nbsp;=&amp;nbsp;new&amp;nbsp;JwtAccessTokenConverter();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;这个使对称密钥，资源服务器里也要使用这个密钥
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jwtAccessTokenConverter.setSigningKey(&amp;quot;ali&amp;quot;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;jwtAccessTokenConverter;
}@Beanpublic&amp;nbsp;TokenStore&amp;nbsp;tokenStore(JwtAccessTokenConverter&amp;nbsp;converter)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;new&amp;nbsp;JwtTokenStore(converter);
}&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;在OAuth2的配置类中添加如下代码，并重启服务：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; has-selection=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;@Overridepublic&amp;nbsp;void&amp;nbsp;configure(AuthorizationServerEndpointsConfigurer&amp;nbsp;endpoints)&amp;nbsp;throws&amp;nbsp;Exception&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;endpoints.authenticationManager(authenticationManager)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;设定配置好的AuthorizationServerTokenServices
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.tokenServices(serverTokenServices())
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.userDetailsService(userDetailsService);
}@AutowiredTokenStore&amp;nbsp;store;@ResourcesJwtAccessTokenConverter&amp;nbsp;converter;private&amp;nbsp;AuthorizationServerTokenServices&amp;nbsp;serverTokenServices(){&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DefaultTokenServices&amp;nbsp;tokenServices&amp;nbsp;=&amp;nbsp;new&amp;nbsp;DefaultTokenServices();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;允许token刷新
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tokenServices.setSupportRefreshToken(true);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;添加刚才的TokenStore
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tokenServices.setTokenStore(store);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;添加token增强，其实就是刚才的转换器，增强的意思就是添加一些自定义的数据到jwt中
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tokenServices.setTokenEnhancer(converter);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;tokenServices;
}&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;然后就可以获取token了&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img alt=&quot;无21标题&quot; loading=&quot;lazy&quot; data-src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183827886-679862582.png&quot; class=&quot;lazyloaded medium-zoom-image&quot; src=&quot;https://img2024.cnblogs.com/blog/3388489/202603/3388489-20260327183827886-679862582.png&quot; style=&quot;margin: 0px; padding: 0px; border: 0px; max-width: 100%; height: auto !important; cursor: zoom-in; transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) !important;&quot;/&gt;&lt;/p&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;现在对资源服务器进行配置，（这时资源服务器就不用连接验证服务器了）然后重启：&lt;/p&gt;&lt;pre class=&quot;highlighter-hljs&quot; highlighted=&quot;true&quot; has-selection=&quot;true&quot; cnb-code-toolbar-active=&quot;true&quot; style=&quot;margin: 10px auto; padding: 0px; transition-duration: 0.2s; transition-property: background, font-size, border-color, border-radius, border-width, padding, margin, color; overflow: auto; font-family: var(--code-font, &amp;#39;&amp;quot;Courier New&amp;quot;, sans-serif, Consolas, Monaco&amp;#39;); position: relative; color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);&quot;&gt;security:
&amp;nbsp;&amp;nbsp;oauth2:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resource:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jwt:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;这里要和验证服务器的密钥一致，这样算出来的签名才能生效
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;key-value:&amp;nbsp;ali&lt;/pre&gt;&lt;p style=&quot;margin: 10px auto; padding: 0px; color: rgb(51, 51, 51); font-family: verdana, Arial, Helvetica, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;这时，就可以携带token直接访问资源服务器了，此时就和验证服务器没啥关系了！&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Wed, 26 Nov 2025 16:18:07 +0800</pubDate></item></channel></rss>