从原理到示例:Java开发玩转MCP——Spring AI Alibaba生态实战指南(TaoToken统一Key接入篇)
1. 为什么 Java 后端需要 MCP从接口方言到统一工具协议如果你写过几年 Spring Boot大概率经历过这种场景业务系统里已经有一堆现成的 Service比如订单查询、库存校验、天气接口、内部工单系统。现在产品说想接个大模型让用户用自然语言就能查数据、触发操作。你第一反应是写 Function Calling结果发现每个模型厂商的 JSON Schema 格式略有差异工具描述要重复写好几遍换一个模型就得改一轮适配层。MCPModel Context Protocol想解决的就是这件事。你可以把它理解成 AI 世界的 USB-C 接口工具提供方按统一协议暴露能力模型侧按统一协议发现和调用工具中间不需要为每个模型单独写胶水代码。对 Java 开发者来说它的价值不在于“又一个新协议”而在于你现有的 Spring Bean 可以很低成本地变成大模型可调用的工具。这篇面向的是已经有 Java 后端经验、想把本地工具能力暴露给大模型的开发者。我会用 Spring Boot Spring AI Alibaba 走一遍完整链路先写一个 MCP Server 把天气查询工具注册出去再写一个 MCP Client 让对话请求自动触发工具调用最后把模型 endpoint 切到 TaoToken 统一 Key 通道用一次真实请求验证工具调用是否成功返回。全程给出可复制的 pom 依赖、application.yml 配置和示例代码你跟着敲就能跑通。先说清楚 MCP 在 Java 侧的两个角色。MCP Server负责暴露工具它可以是 Stdio 模式本地进程通信适合开发调试也可以是 SSE 模式HTTP 长连接适合远程服务。MCP Client负责连接 Server、拉取工具列表并把工具注册进 ChatClient这样用户提问时模型就能自动决定调哪个工具。Spring AI Alibaba 在这两层都提供了 starter省掉了手写协议解析的活。我试过把公司内部一个工单查询接口包成 MCP 工具从写代码到对话验证成功大概花了四十分钟其中一半时间在调依赖版本。所以下面我会把版本对齐这件事讲细一点避免你在NoSuchMethodError上卡住。核心检索词先摆出来Java 接入 MCP、Spring AI Alibaba MCP Server、Spring Boot MCP Client、TaoToken 统一 Key。这几个词贯穿全文你搜资料时也可以按这个方向找。2. TaoToken 前置统一 Key 通道与模型 endpoint 准备在写代码之前先把模型侧的通路准备好。Spring AI Alibaba 默认会去连各家模型的官方 endpoint但如果你想像我一样用一套 Key 管理多个模型、并且方便在 Claude、Qwen、DeepSeek 之间切换做工具调用测试可以把 endpoint 指到 TaoToken 的统一通道。TaoToken 在这里扮演的是统一 API 入口你拿到一个 Key就能通过兼容 OpenAI 协议的接口访问多个模型。对 Spring AI 来说这意味着你只需要配base-url和api-key模型名换成对应的 Model ID 即可代码层几乎不用动。具体操作路径是这样的先到官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册账号然后进控制台创建 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。创建完记得复制保存页面刷新后就不再完整显示了。这里有个细节要注意Spring AI Alibaba 的 OpenAI 兼容配置里base-url一般填到/v1这一层而 TaoToken 的 API 根地址是 https://taotoken.net/api 。所以你在 yml 里写的完整 base-url 应该是https://taotoken.net/api具体路径拼接由框架的 OpenAI 客户端处理。如果你用的是其他框架记得确认它是否会自动补/v1/chat/completions。模型选择上工具调用能力比较稳的可以选 Claude 系列或 Qwen 系列。你可以在模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 先手动测一下模型能不能正常返回确认 Key 有效再进代码环节。这一步别省我见过太多人代码写完报 401最后发现是 Key 复制时带了空格。如果你后面打算长期做编码类 Agent可以了解下 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 它更适合高频调用场景。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 遇到协议细节可以对照查。前置准备清单一个可用的 API Key、确认 base-url 为https://taotoken.net/api、选好一个支持工具调用的 Model ID。这三样齐了下面直接进配置。3. 可复制配置pom 依赖、application.yml 与 MCP Server 代码这一节是全文的技术核心我给的都是能直接粘贴的片段。先对齐版本Spring Boot 用 3.3.xSpring AI Alibaba 用 1.0.0-M6.1 附近的版本Spring AI 用 1.0.0-M6。版本错位是 MCP starter 报错的头号原因建议你先在 pom 里统一管理。先看 pom.xml 的依赖部分。MCP Server 和 Client 的 starter 要分开引另外加上 OpenAI 兼容的模型 starterproperties java.version17/java.version spring-boot.version3.3.5/spring-boot.version spring-ai.version1.0.0-M6/spring-ai.version spring-ai-alibaba.version1.0.0-M6.1/spring-ai-alibaba.version /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MCP Server把本地工具暴露出去 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-server-spring-boot-starter/artifactId version${spring-ai.version}/version /dependency !-- MCP Client连接 Server 并注册工具 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-client-spring-boot-starter/artifactId version${spring-ai.version}/version /dependency !-- OpenAI 兼容模型接入 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId version${spring-ai.version}/version /dependency /dependencies接下来是 application.yml。这里同时配了模型通道和 MCP Server 的 SSE 模式。注意base-url指向 TaoTokenapi-key换成你自己的server: port: 8080 spring: application: name: mcp-demo ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: claude-3-5-sonnet-20241022 temperature: 0.7 mcp: server: name: java-mcp-server version: 1.0.0 type: SYNC sse-endpoint: /mcp把 Key 放环境变量是个好习惯别硬编码进 yml。启动前export TAOTOKEN_API_KEY你的Key即可。然后是 MCP Server 的工具实现。Spring AI 用Tool注解标记方法ToolParam描述参数框架会自动生成 JSON Schemaimport org.springframework.ai.tool.annotation.Tool; import org.springframework.ai.tool.annotation.ToolParam; import org.springframework.stereotype.Service; Service public class WeatherToolService { Tool(name get_weather, description 查询指定城市的实时天气) public String getWeather( ToolParam(description 城市名称例如北京、杭州) String city) { // 实际项目替换为真实气象 API 调用 return String.format(%s晴25℃湿度 40%%, city); } Tool(name query_order, description 根据订单号查询订单状态) public String queryOrder( ToolParam(description 订单号纯数字) String orderId) { return String.format(订单 %s 状态已发货预计明天送达, orderId); } }工具注册需要一个配置类把 ToolCallbackProvider 暴露成 Beanimport org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.ai.tool.method.MethodToolCallbackProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class McpServerConfig { Bean public ToolCallbackProvider weatherTools(WeatherToolService service) { return MethodToolCallbackProvider.builder() .toolObjects(service) .build(); } }到这里 Server 侧就完成了。启动后访问http://localhost:8080/mcp应该能看到 SSE 连接建立。如果你只想本地调试可以把sse-endpoint去掉改用 Stdio 模式启动但 SSE 更适合后面 Client 远程连接。4. 验证请求MCP Client 触发工具调用并确认返回Server 跑起来后写 Client 来验证整条链路。Client 的职责是连接 MCP Server、拉取工具列表、注入 ChatClient然后你发一句自然语言看模型是否自动调用了工具。先写 MCP Client 的连接配置。Spring AI 的 MCP Client 支持 SSE 和 Stdio 两种 transport这里用 SSE 连本地 8080import org.springframework.ai.mcp.client.McpClient; import org.springframework.ai.mcp.client.transport.SseClientTransport; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class McpClientConfig { Bean public McpClient mcpClient() { SseClientTransport transport new SseClientTransport(http://localhost:8080/mcp); return McpClient.builder() .transport(transport) .clientInfo(java-mcp-client, 1.0.0) .build(); } }然后把它和 ChatClient 串起来。关键点是defaultTools接收 ToolCallbackProviderMCP Client 拉到的工具会通过它注册进去import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.mcp.client.McpClient; import org.springframework.ai.tool.ToolCallbackProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class ChatClientConfig { Bean public ChatClient chatClient(ChatClient.Builder builder, McpClient mcpClient) { ToolCallbackProvider tools mcpClient.toolCallbackProvider(); return builder .defaultTools(tools) .build(); } }写一个 Controller 做验证入口import org.springframework.ai.chat.client.ChatClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; RestController public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient chatClient) { this.chatClient chatClient; } GetMapping(/ask) public String ask(RequestParam String q) { return chatClient.prompt(q).call().content(); } }启动两个服务或者同一个进程里先起 Server 再起 Client然后发请求curl http://localhost:8080/ask?q帮我查一下杭州现在的天气预期返回类似杭州晴25℃湿度 40%。这说明模型识别到用户意图自动选择了get_weather工具传入了city杭州并拿到了工具返回值。你可以再试一句订单 123456 到哪了看它是否切换到query_order工具。如果返回的是模型自己编的天气而不是工具返回的固定格式说明工具没注册成功。这时候去看启动日志里有没有Registered tools: [get_weather, query_order]这类输出。没有的话检查 ToolCallbackProvider 的 Bean 是否被扫描到以及 MCP Client 是否成功连上了 SSE endpoint。验证模型本身是否正常可以先用模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 发一句普通对话确认 Key 和模型没问题再排查 MCP 层。这个顺序能帮你快速定位是模型通道问题还是工具注册问题。5. 常见报错排查401、local proxy failed 与 reading choices这一节按真实报错来。我把踩过的坑按错误信息分类你对照日志找。401 Unauthorized。最常见的原因是 Key 无效或没带上。检查三处环境变量TAOTOKEN_API_KEY是否真的 export 了echo $TAOTOKEN_API_KEY看有没有值yml 里api-key的占位符拼写是否一致Key 前后有没有多余空格或换行。还有一种情况是 base-url 写成了https://taotoken.net少了/api导致请求打到了错误路径返回 401。正确写法是https://taotoken.net/api。local proxy failed / connection refused。这个通常出现在 MCP Client 连 Server 时。如果你用 SSE 模式确认 Server 已经启动并且 8080 端口在监听lsof -i:8080。如果 Server 和 Client 在不同机器把http://localhost:8080/mcp换成实际 IP。另外注意 SSE endpoint 路径要和 yml 里的sse-endpoint完全一致大小写都别错。reading choices 相关报错比如Cannot read field choices because response is null或choices解析失败。这多半是模型返回体不符合 OpenAI 格式或者模型名写错了。检查spring.ai.openai.chat.options.model是否是你账号下可用的 Model ID。有些模型不支持工具调用返回结构会不一样换一个支持 function calling 的模型再试。如果用的是 TaoToken 通道确认模型名和文档里列的一致。NoSuchMethodError / ClassNotFoundException。这是版本冲突的典型症状。Spring AI 和 Spring AI Alibaba 的 milestone 版本之间依赖关系比较敏感建议用mvn dependency:tree看下spring-ai-core是不是被拉了两个版本。统一在 properties 里管理版本号别在单个 dependency 里写死。工具被调用但参数为空。检查ToolParam的 description 是否写清楚模型靠这个理解参数含义。参数类型尽量用 String、int 这类简单类型复杂对象容易生成错误的 JSON Schema。OAuth / token 过期类报错。如果你用的是需要 OAuth 的模型通道注意 token 有效期。TaoToken 的 Key 是长期有效的但如果你在代码里又套了一层自己的鉴权记得把两层分开排查。接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里有协议细节遇到不确定的字段可以去对。排查顺序建议先确认模型通道通用 chat 页面测再确认 MCP Server 起没起再确认 Client 连没连上最后看工具注册日志。一层层往下别一上来就改代码。6. 语义一致 CTA把统一 Key 通道用进你的 Java Agent走到这里你已经跑通了 Spring Boot Spring AI Alibaba 的 MCP 全链路Server 暴露工具、Client 注册工具、模型自动调用、结果返回。接下来可以做的扩展方向有几个把内部工单、库存、审批这些 Service 陆续加上Tool注解让它们变成模型可调用的能力把 SSE 模式部署到内网让多个 Client 共享同一套工具或者把 endpoint 固定到 TaoToken 统一通道用一套 Key 管理多个模型的切换测试。如果你在排障或接入阶段卡住了优先看 API Keys 管理页 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 确认 Key 状态再对照接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 检查协议字段。想先验证模型本身能不能正常对话和工具调用用模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 最快。如果你打算长期做编码类 Agent、高频调用工具Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 会更合适。最后留一个实用技巧把get_weather这类高频工具的返回值加一层本地缓存比如 Caffeine模型连续问同一个城市时就不用重复打外部 API。工具方法本身不用改在 Service 里加Cacheable就行。这个优化在真实项目里能省不少调用量。

相关新闻

AI Agent Harness Engineering 农业应用案例:精准种植、病虫害识别与产量预测的 TaoToken 配置实践

AI Agent Harness Engineering 农业应用案例:精准种植、病虫害识别与产量预测的 TaoToken 配置实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 21:54:08 阅读更多 →
深度研究报告:Codex 与 Claude Code 的 Agent Loop 原理与 MCP 协议应用全面对比

深度研究报告:Codex 与 Claude Code 的 Agent Loop 原理与 MCP 协议应用全面对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 21:54:08 阅读更多 →
Cursor 手型小手样式全解析:从 CSS cursor 到 TaoToken 配置的完整指南

Cursor 手型小手样式全解析:从 CSS cursor 到 TaoToken 配置的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 21:54:08 阅读更多 →

最新新闻

大数据挖掘工程实战:从架构设计到网约车项目落地

大数据挖掘工程实战:从架构设计到网约车项目落地

数据挖掘这词儿,圈内人听了不觉得新鲜,圈外人一听就犯迷糊:“不就是跑几个模型、出几张报表吗?”真不是。我做了这么多年大数据项目,最深的体会是:数据挖掘不是工具链的堆砌,而是把业务问题翻译…

2026/10/1 2:27:57 阅读更多 →
Hindsight:Chromium浏览器痕迹解析与时间线分析利器

Hindsight:Chromium浏览器痕迹解析与时间线分析利器

Hindsight 这个词,直译是“后见之明”,但在数字取证圈的桌面工具栏里,它是目前解析 Chromium 系浏览器痕迹最顺手的开源工具之一。我第一次在事件响应现场用它,是在一台还在运行的 Windows 机器上,把 Chrome 用户目录拷…

2026/10/1 2:27:57 阅读更多 →
VS Code AHP协议:Dev Container的AI控制权革命

VS Code AHP协议:Dev Container的AI控制权革命

1. 这不是“AI插件升级”,而是开发环境控制权的范式转移最近打开 VS Code,弹窗提示“新版本已就绪”,点开更新日志第一行就写着:“支持 AI 智能体通过 AHP 协议直接操作 Dev Container”。我下意识划了两下——这行字没配图、没链…

2026/10/1 2:27:57 阅读更多 →
Win7/8.1老电脑用SteamCMD命令行下载更新游戏服务端全攻略

Win7/8.1老电脑用SteamCMD命令行下载更新游戏服务端全攻略

如果你手头还有一台Windows 7/8/8.1的老电脑,又不想让Steam客户端吃掉几百MB内存,还希望能在服务器或者后台环境里把游戏和游戏服务端拉下来跑起来,SteamCMD才是真正趁手的家伙。它没有花哨的图形界面,也不带商店推荐和社区弹窗&a…

2026/10/1 2:27:57 阅读更多 →
微信开源RAG知识库项目拆解:文档解析、混合检索与重排实战

微信开源RAG知识库项目拆解:文档解析、混合检索与重排实战

"微信开源了一个神级知识库项目"——这个消息刚出来那天,我的技术交流群直接炸了。有人第一时间甩了个链接,说这不就是个RAG项目吗,至于这么大惊小怪。我当时没急着站队,先自己把这个项目clone下来,跑通了一…

2026/10/1 2:27:57 阅读更多 →
JMeter压力测试从入门到进阶:安装配置、脚本编写、结果分析与分布式压测

JMeter压力测试从入门到进阶:安装配置、脚本编写、结果分析与分布式压测

1. JMeter压力测试工具的整体定位与选型思路做Java后端的朋友,逃不掉一个环节:接口上线前得压一压,看看服务在高并发下到底撑不撑得住。我最早接触压测是用ab(Apache Bench)跑个简单接口,后来遇到需要登录态…

2026/10/1 2:26:57 阅读更多 →

日新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:01:17 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/30 13:14:22 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/30 18:13:06 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/30 13:14:49 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:01:17 阅读更多 →