尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Spring AI实战:从Tools到RAG再到Agent的完整学习路线

Spring AI实战:从Tools到RAG再到Agent的完整学习路线 这次我们直接聊 Spring AI。它不是又一个“AI 概念中间件”而是 Java 生态里把大模型接到业务系统的正规军Spring 官方维护Spring Boot 原生集成既有 ChatClient 这种开箱即用的对话封装又能通过 Tools 让模型调用业务方法再通过 RAG 把企业知识库变成回答依据最后用 Agent 把多步任务串起来。网上这套被很多人收藏的保姆级教程标题里带了 Langchain4j、Tools、RAG、Agent 四个关键词正好对应了 Java 开发者入局大模型应用开发最常见的四条路官方 Spring AI、第三方 Langchain4j、模型函数调用、知识库增强、自主 Agent。这篇文章就把这条学习路线展开成一份可落地的实践清单从项目搭建到工具调用再到知识库检索和 Agent 编排每一节都能直接对着操作。核心路径很简单先用 Spring Boot 起一个能对话的服务再给模型开放两三个真实工具接着把 PDF、Markdown、TXT 文档做成向量知识库最后让模型在多个工具之间自主决策完成一个人工智能体。读完你不会得到一个花哨演示而是能判断自己的业务到底需要哪些模块以及每一步的验证方法是什么。1. Spring AI 核心能力速览先把能力边界拉清楚避免一上来被各种概念绕晕。能力项说明技术定位Java / Spring Boot 生态的大模型应用开发框架主要功能对话、结构化输出、函数调用 Tools、RAG 知识库、Agent 编排官方属性Spring AI 由 Spring 官方维护Langchain4j 是 Java 社区流行的第三方 LLM 框架模型接入方式OpenAI 兼容 API、本地 Ollama、各类云厂商模型以实际依赖为准启动方式Spring Boot Web 服务支持 REST 接口是否支持 API支持Controller / WebFlux 均可暴露接口是否支持批量任务支持但需要自行设计任务队列和并发策略学习门槛中低有 Spring Boot 基础即可上手适合场景企业 Java 项目接入 LLM、知识库问答、自动化 Agent 服务从表格能看出Spring AI 不是用来做模型训练的平台而是解决“模型怎么接入业务”的问题。它的核心价值是统一客户端让你不用每次手动拼 HTTP 请求也不用自己处理 JSON 解析、Token 计数、历史消息等琐碎逻辑。Langchain4j 是另一条路线它受 Python 生态的 LangChain 启发适合已经熟悉 LangChain 概念、想在 Java 环境里快速迁移的团队。两者不是互斥关系教程里放在一起讲是为了让读者对 Java LLM 开发有两种可选思路一个走 Spring 官方生态一个走中立轻量框架。实际项目中选一条主线即可不需要同时引入两套。2. 适用场景与学习路线先判断这套技术栈适不适合你再决定投入多少时间。最适合的读者有两类。第一类是 Java 后端工程师已经在维护 Spring Boot 项目想在现有系统里增加智能问答、内容总结、客服助手等能力不希望引入 Python 服务。第二类是技术团队负责人想评估自建 RAG 和 Agent 的可行性对比自己开发与采购 SaaS 的差异。2.1 典型使用场景企业知识库问答把产品文档、运维手册、制度文件切块存入向量库用户提问时先检索再生成答案。数据查询助手模型通过函数调用访问订单接口、库存服务、用户中心用自然语言完成查询。内容处理流水线批量总结工单、抽取合同关键字段、整理会议纪要并把结果写回业务库。自动化 Agent让模型根据目标拆解步骤依次调用多个工具完成任务例如“查一下今天的新增订单并生成一份简要报告”。2.2 学习路径建议从 0 到 1 建议按下面顺序推进先跑通 ChatClient 对话掌握 Prompt、温度参数、历史消息。再实现一个最简单的 Tools 工具理解函数调用是怎么返回业务数据的。然后做 RAG重点看文档切块、Embedding、向量检索的完整链路。最后用 Tools 加 RAG 组合出 Agent让模型自主决定调用哪些能力。这套路径也正好解释了为什么“Tools、RAG、Agent”这三个词经常一起出现Tools 让模型能动手操作业务系统RAG 让模型能读取知识库里的资料Agent 则把两者组合成自主执行闭环。2.3 使用边界与合规提醒不是所有场景都适合直接上大模型。高精度数值计算、实时账户扣款、敏感权限操作不建议交给模型直接执行。RAG 只能做到“召回相关内容”不能保证每一次检索都精确命中。Tools 函数调用也必须做权限校验和审计日志不能因为模型生成了参数就默认放行。涉及用户数据、企业文档、人脸信息、声音素材、版权内容时必须确认来源合法并完成脱敏处理。本地部署模型时应该从模型官方渠道获取权重文件避免使用来源不明的整合包。对外提供服务时要在接口层增加用户身份校验和内容审核。3. 环境准备与前置条件在开始写代码之前先把本机环境确认一遍。这套教程不要求你有一张顶级显卡因为大部分训练和推理都可以通过 API 完成但如果要在本地跑模型显卡显存会影响体验。3.1 基础环境清单依赖建议要求JDKJDK 17 及以上构建工具Maven 3.8 或 Gradle 7.xSpring BootSpring Boot 3.x与当前 Spring AI 版本匹配模型访问OpenAI 兼容 API 或本地 Ollama向量数据库开发阶段可用内存向量库生产建议 Milvus / PgVector磁盘空间本地模型视量化大小而定API 模式只需几百 MB 缓存要注意Spring AI 和 Langchain4j 的版本更新速度都不慢不同版本的 API 会有差别。教程代码如果报编译错误优先检查自动注入的ChatClient.Builder、VectorStore等类是否在当前版本中改名或移动了包路径。3.2 本地模型的可选方案如果不想注册模型服务商的 API可以用 Ollama 跑一个本地模型。以 Qwen 系列为例本地安装 Ollama 后执行ollama pull qwen2.5:7b然后确认 Ollama 的兼容接口处于启动状态。Ollama 默认监听 11434 端口并提供 OpenAI 兼容的/v1路径。用命令行验证curl http://localhost:11434/v1/models能够返回模型列表就说明本地模型服务可用。Embedding 模型也需要准备一个例如用ollama pull qwen-embedding具体模型名以本机实际拉取情况为准。显存占用会随模型大小和推理长度变化没有固定值实际部署时用nvidia-smi观察即可。3.3 向量数据库准备开发阶段可以先用 Spring AI 自带的 SimpleVectorStore直接把向量存在本地文件里适合跑通流程。进入真实性测试后建议切换 Milvus、PgVector 或 Redis 等向量存储方案。Milvus 需要启动 Docker 或独立服务端口默认 19530PgVector 则需要 PostgreSQL 实例。第一次跑 RAG 时不要同时引入太多中间件先跑通再扩展。4. 从零搭建 Spring AI 项目这一节用一个最小可运行的对话项目把 Spring AI 的开发链路完整走一遍。所有代码都基于通用模板实际版本和包名需要按你的构建文件调整。4.1 创建 Maven 工程最简单的做法是使用 Spring Initializr 创建一个 Spring Boot 3 项目然后在pom.xml中引入 Spring AI 依赖。版本建议使用 Spring 官方 BOM 统一管理dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version替换为当前版本/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement随后加入具体模块dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-model-openai/artifactId /dependency如果你想走 Langchain4j 路线则在 Maven 中引入它的核心包dependency groupIddev.langchain4j/groupId artifactIdlangchain4j/artifactId version替换为当前版本/version /dependency两条路线可以分别学习不建议在同一个服务里同时依赖两套会话管理逻辑否则后期待维护成本会比较高。4.2 配置模型服务地址在application.yml中配置 OpenAI 兼容的地址。如果本机 Ollama 已经被我拉起来可以这样写spring: ai: openai: base-url: ${AI_BASE_URL:http://localhost:11434/v1} api-key: ${AI_API_KEY:unused} chat: options: model: qwen2.5:7b环境变量AI_BASE_URL的目的是让你在云端部署和本地开发之间快速切换不需要改代码。如果使用的是在线模型服务就把base-url和api-key替换成服务商提供的真实值。4.3 第一个对话接口Spring AI 的常用门面是ChatClient。它像 JdbcTemplate 一样强调简单直接构建一个ChatClient然后使用prompt().user().call()完成一次对话。RestController public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient.Builder builder) { this.chatClient builder.build(); } GetMapping(/chat) public String chat(RequestParam(defaultValue 介绍一下你自己) String message) { return chatClient.prompt() .user(message) .call() .content(); } }启动服务后访问http://localhost:8080/chat?message你好能返回一段文本就算成功。4.4 验证标准第一次启动时重点观察三点模型地址是否能连通、返回内容是否正常、日志里有没有报错。如果请求一直超时先检查base-url路径是否带/v1。如果返回“model not found”则检查模型名称是否和本地拉取的名字一致。这里最容易犯的错误是复制了教程里的模型名却没有本机ollama list确认。5. Tools 函数调用让模型操作真实业务ChatClient 只能完成纯文本对话真正让模型具备业务能力的是 Tools 函数调用。举个例子用户问“我的订单到哪了”模型本身并不知道订单数据但可以通过工具定义告诉模型“我提供了一个查询订单状态的函数你需要提取订单号并调用它”。模型生成的不是最终答案而是一个工具调用请求业务系统执行完成后把结果回传给模型由模型组织成最终回答。5.1 定义工具类在 Spring AI 中你可以通过注解标记一个普通 Bean 方法为工具Component public class OrderTools { private final OrderService orderService; public OrderTools(OrderService orderService) { this.orderService orderService; } Tool(description 根据订单号查询订单状态) public String getOrderStatus(ToolParam(description 订单编号) String orderId) { Order order orderService.findByOrderId(orderId); if (order null) { return 未找到订单; } return 订单状态 order.status() 金额 order.amount(); } }Tool注解会把方法描述传给模型让模型在合适的时候调用。ToolParam则描述参数含义方便模型正确提取参数。这里的关键点是模型不会执行你的 Java 方法它只是生成一个结构化调用请求真正执行的是 Spring AI 容器。5.2 把工具绑定到 ChatClient创建ChatClient时通过.defaultTools()注册工具Bean ChatClient chatClient(ChatClient.Builder builder, OrderTools orderTools) { return builder .defaultSystem(你是一个订单客服助手查询订单信息时请使用工具不要编造数据。) .defaultTools(orderTools) .build(); }然后启动服务在聊天接口里输入“帮我查一下订单号 OD20250101 的状态”如果日志中出现工具调用记录并且返回内容包含模拟或真实订单状态说明函数调用链路已经打通。5.3 结构化输出Tools 场景下经常需要把结果封装成对象。Spring AI 支持把模型输出解析为 Java 实体类例如定义一个订单信息实体public record OrderInfo( String orderId, String status, double amount ) { }然后在对话请求中指定实体类型OrderInfo info chatClient.prompt() .user(请从如下订单中提取订单号、状态和金额 text) .call() .entity(OrderInfo.class);结构化输出在批量抽取字段时非常有用。它避免了“从一串自然语言里正则抓取字段”的脆弱实现也让下游数据库写入更可靠。6. RAG 知识库文档加载、切块、向量化与检索增强RAG 是 Spring AI 教程里技术链最长的一节也是大多数企业真正会落地的功能。完整的 RAG 流程可以拆成两段离线入库、在线问答。6.1 RAG 完整链路离线入库阶段加载文档 - 切块 - 向量化 - 写入向量库。在线问答阶段用户提问 - 问题向量化 - 相似度检索 - 拼装上下文 - 模型生成。以企业产品文档为例先准备一个 PDF 或 Markdown 文件再写一个入库组件。Spring AI 中常见的写法类似Component public class DocumentIngestService { private final VectorStore vectorStore; private final TextSplitter textSplitter; public DocumentIngestService(VectorStore vectorStore, TextSplitter textSplitter) { this.vectorStore vectorStore; this.textSplitter textSplitter; } public void load(Resource resource) { // 1. 读取文档 ListDocument documents new PagePdfDocumentReader(resource).get(); // 2. 切块 ListDocument chunks textSplitter.apply(documents); // 3. 向量化并入库 vectorStore.add(chunks); } }这段代码在真实项目中需要按当前 Spring AI 版本的 API 调整特别是PagePdfDocumentReader的包名可能出现变化。但整体思路是一致的读文档、切块、存向量。6.2 切块策略怎么选切块是 RAG 调优最重要的环节之一。切得太大检索召回的内容会塞进大量无关信息切得太小语义不完整模型难以理解上下文。比较实用的策略有几种策略适合场景注意事项固定大小切块通用文本、日志、新闻实现简单但可能截断句子按段落切块文档结构清晰的 Markdown/Word保留语义但文档需要规范父子切块问答类知识库父块负责上下文子块负责检索语义切块内容主题变化较大的文档实现复杂需要额外模型判断边界第一次实验建议从“按段落切块”开始先看检索效果再决定是否优化。不要一上来就追求最复杂的切块方案否则很难定位效果差的真正原因。6.3 向量存储配置以 Milvus 为例引入向量库 Starter 后需要配置连接信息spring: ai: vectorstore: milvus: host: ${MILVUS_HOST:localhost} port: 19530 database: default collection-name: spring_ai_demo如果使用 PgVector则把对应的 Starter 依赖引入并在数据源配置中指向 PostgreSQL。开发阶段不要求立刻切换专业向量库先使用内存实现观察流程数据量大了再迁移。6.4 在线问答检索当知识库入库完成后问答服务需要先检索再生成回答。使用 Spring AI 的QuestionAnswerAdvisor可以把检索和生成串起来RestController public class RagController { private final ChatClient chatClient; public RagController(ChatClient.Builder builder, VectorStore vectorStore) { this.chatClient builder .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore)) .build(); } GetMapping(/ask) public String ask(RequestParam String question) { return chatClient.prompt() .user(question) .call() .content(); } }启动后输入“文档里提到什么部署要求”如果答案内容明显来自库中文档并且来源可追溯RAG 链路就完成了。注意RAG 的最大问题往往不是模型而是“检索不到”或“检索太杂”。后续建议增加相关性重排用更好的 Embedding 模型或者调整 TopK 参数。7. Agent 开发多轮记忆、自动规划与工具组合把 Tools 和 RAG 组合起来就能得到一个极简 Agent。Agent 的核心理念是模型不再只是单轮回答问题而是围绕用户目标反复调用工具、观察结果、决定下一步动作。7.1 极简 Agent 设计思路一个轻量 Agent 的核心循环可以描述为系统设定告诉模型你可以使用哪些工具目标是什么。模型生成回答或工具调用请求。如果有工具调用请求应用执行工具并返回结果。模型根据结果继续生成直到给出最终答案或达到最大轮数。整个过程中保持对话历史让模型记住之前已经执行过哪些步骤。7.2 用 Spring AI 实现一个简化 Agent下面是一个伪代码风格的最小模板实际项目需要结合你的模型能力和工具定义调整public String runAgent(String userGoal) { StringBuilder conversation new StringBuilder(); conversation.append(用户目标).append(userGoal).append(\n); for (int step 0; step 5; step) { String response chatClient.prompt() .user(conversation.toString()) .call() .content(); // 假设模型返回 JSON包含 action 和 actionInput ToolCallRequest request parseToolCall(response); if (request null) { return response; } String toolResult executeTool(request); conversation.append(工具调用结果).append(toolResult).append(\n); } return 达到最大轮数未能完成目标; }这个模板虽然简单但已经包含了 Agent 的三个核心要素循环、工具执行、结果回填。真实项目会让模型输出更严格的工具调用结构而不是用自然语言拼接但原理一致。7.3 Langchain4j 中的 Agent 思路Langchain4j 的AiServices提供了更高级的封装。你可以把工具方法定义成接口由框架动态生成代理类public interface Assistant { String chat(String userMessage); }然后绑定工具类、EmbeddingStore 和语言模型。具体写法因版本而异教程里重点理解的概念是框架会管理模型的函数调用请求、工具执行结果和对话历史。熟悉这个概念后无论切换 Spring AI 还是 Langchain4j底层心智模型都通用。7.4 Agent 开发中的坑Agent 很容易出现两类问题一类是模型反复调用同一个工具进入死循环另一类是模型生成一个不存在的工具参数导致执行异常。解决办法是给 Agent 设置最大轮数、增加工具参数校验、关键操作要求人工确认。尤其涉及数据库修改、发送消息、删除文件等操作必须加权限控制不能全权交给模型自动执行。8. 接口 API 与批量任务Spring AI 服务本质上是一个 Spring Boot 应用对外暴露 REST API 是顺理成章的事。但接口层和批量任务层需要单独设计否则一旦流量上来模型调用很容易被打爆。8.1 暴露一个标准聊天接口在ChatController中增加 POST 接口适合客户端传入参数并获取结构化返回RestController RequestMapping(/api/ai) public class AiController { private final ChatClient chatClient; public AiController(ChatClient.Builder builder) { this.chatClient builder.build(); } PostMapping(/chat) public MapString, String chat(RequestBody ChatRequest request) { String answer chatClient.prompt() .user(request.message()) .call() .content(); return Map.of(answer, answer); } }对应的请求体可以是一个 Java Recordpublic record ChatRequest(String message) { }测试时可以使用 curl 调用curl -X POST http://localhost:8080/api/ai/chat \ -H Content-Type: application/json \ -d {message: 请用一句话介绍什么是 RAG}如果返回正常说明 API 已经跑通接下来可以接入前端应用或对接企业的 IM 机器人。8.2 使用 Python 脚本调用接口虽然这套技术栈是 Java但接口是标准 HTTPPython 也能方便测试import requests url http://localhost:8080/api/ai/chat payload {message: Spring AI 中 Tools 是什么} response requests.post(url, jsonpayload, timeout60) print(response.json())批量测试时可以准备一个questions.txt逐行读取并调用接口把结果写入 CSV 或数据库中。调用时要注意设置合理超时避免单条请求卡死整个脚本。8.3 批量任务的工程化思路批量处理场景主要分两类批量入库和批量问答。批量入库建议采用生产者消费者模式生产者扫描文档目录消费者负责切块、向量化、写入向量库。关键点是断点续传已经处理过的文档要跳过避免重复入库。批量问答则需要控制并发。模型服务通常有限流策略直接用线程池压测很容易报 429 或超时。一个稳妥的做法是设置固定线程池并加入重试机制ExecutorService executor Executors.newFixedThreadPool(4); for (String question : questions) { executor.submit(() - { try { // 调用 AI 接口保留日志 } catch (Exception e) { // 记录失败问题后续重试 } }); } executor.shutdown();重试时建议增加退避策略比如等待几秒后再执行而不是无限重试。可以在失败日志里记录请求参数、错误信息和原始响应方便定位是模型问题还是数据问题。9. 资源占用与性能观察教程能不能在生产环境落地资源占用是关键指标。这里不给你一个固定的显存数字因为不同模型、量化等级、并发数差异很大。这里给出观察方法和高风险点。9.1 显存占用怎么看如果你使用本地模型先启动模型服务然后用系统命令观察nvidia-smi重点看显存使用率、GPU 利用率和温度。Ollama 也支持查看已加载模型的状态ollama ps这个命令会显示当前模型驻留显存的大小。如果显存长期接近上限可以减小上下文长度、降低 batch 大小或换量化等级更高的模型。9.2 影响性能的主要因素上下文长度传入的文档越多Token 消耗越大响应越慢。切块数量RAG 检索如果一次给模型塞回太多文档片段生成速度会明显下降。并发数API 模式的瓶颈通常在服务商限流本地模型的瓶颈通常是显存和算力。工具定义数量Tools 定义过多时模型需要处理更长的函数描述也会增加延迟。如果发现响应时间从 2 秒涨到 10 秒优先检查是不是上下文太长。调试阶段打印每次请求的 Token 使用情况是判断性能瓶颈最直接的方法。9.3 降低资源占用的通用手段使用 Embedding 模型和对话模型分离不用让一个模型同时承载两类任务。RAG 检索时先设置较小的 TopK例如 3 到 5再结合重排提升精度。批量任务放到低峰期执行避免和线上实时请求争抢资源。用 API 模式快速验证功能确认稳定后再转本地模型调优。限制 Agent 最大轮数防止模型无限调用工具造成消耗指数增长。10. 常见问题与排查方法在这套教程的学习过程中大部分报错都集中在下面几个点上。遇到问题时先不要急着改代码按表格顺序排查。问题现象可能原因排查方式解决方案启动报依赖冲突Spring Boot 版本与 Spring AI 版本不匹配查看 Maven 依赖树改用 Spring Initializr 选择兼容版本调用模型报连接超时base-url配置错误或模型服务未启动先用 curl 测试模型接口确认地址带/v1确认端口和模型名返回内容为空模型超时或输出内容被拦截查看日志和原始响应增加超时时间检查上下文是否超限结构化输出解析失败模型返回了不符合 JSON 格式的内容打印原始 content在 Prompt 中强调输出格式或增加重试次数RAG 回答与文档无关切块过大或检索 TopK 太小打印检索命中的片段调整切块长度、增大或减小 TopK、换 Embedding 模型Tools 工具没有被调用工具描述不清晰或参数说明缺失查看模型是否返回函数调用请求完善Tooldescription示例参数名称与业务一致Agent 循环调用同一工具缺少终止条件或工具结果没有影响下一轮打印调用轮数和工具结果设置最大轮数增加结果判断逻辑端口冲突本地已有服务占用 8080使用lsof -i :8080查看在启动参数中指定--server.port8081本地模型推理慢显存不足或模型量化等级过高使用ollama ps观察显存更换量化模型缩短上下文降低并发批量任务卡住单条请求没有设置超时检查线程池日志为 HTTP 客户端和ChatClient设置超时时间特别强调一下 RAG 排查顺序先确认文档确实入库再确认检索能召回最后才考虑模型生成问题。很多人一上来就调 Prompt但其实问题出在切块和检索参数上。11. 最佳实践与合规建议这套 Spring AI 技术栈要真正应用于生产不能只满足于“能跑通”还需要从工程和合规两个角度做收尾。11.1 工程化建议配置统一放到环境变量中包括模型地址、API Key、VectorStore 地址不要硬编码。接口层增加简单的访问控制至少按用户区分不能让所有调用共享一个模型额度。模型输出不直接写入核心数据库先经过服务层校验和脱敏。为每次请求生成唯一 ID在日志里串联模型调用、工具执行和最终响应。保留一份最小可运行配置方便日后升级和排查问题。首次上线前用一批真实问题做回归测试统计准确率和失败率。11.2 成本控制建议如果是付费模型 API需要特别关注 Token 消耗。对话历史越攒越长每次请求成本都会增加。RAG 检索时不要把所有文档片段都塞进 Prompt精确控制返回片段数量比单纯追求“越多越好”更有效。Tools 定义过多也会变相增加模型输入的 Token 量建议只给 Agent 暴露当前业务场景必需的工具。11.3 合规与安全边界使用 RAG 知识库时要确认文档来源合法且不包含未脱敏的个人信息。对外对话接口建议做输入拦截和输出审核防止模型被诱导输出敏感内容。Agent 中涉及订单查询、用户数据查询时必须校验调用者权限不能因为模型有工具就绕过业务权限体系。涉及人脸、声音、肖像等内容处理时必须取得明确授权并遵守当地法律法规。12. 总结与下一步Spring AI 最值得上手的一点是它把“大模型接入企业 Java 项目”这件事变成了标准 Spring Boot 开发流程。你不需要先学 Python也不用重写一套服务只要掌握 ChatClient、Tools 和 VectorStore 三个核心抽象就能搭建一条完整的 AI 应用链路。建议你从最简单的最小工程开始先验证模型能通再为一个具体业务场景写两个工具然后准备一两篇文档做 RAG。不要一开始就追求复杂的 Agent 编排先把单点能力测稳定再把它们组合起来。最容易踩的坑有两个一是版本和 API 不匹配看到代码报错先检查依赖二是 RAG 效果不好时盲目调 Prompt结果问题出在文档切块和检索参数上。提前把这几个点记住能节省大量时间。下一步可以继续扩展的方向不少接入更专业的向量数据库做混合检索加重新排序把 Langchain4j 的轻量封装引入团队对比验证或者把当前 Agent 接入企业 IM 机器人让用户在聊天窗口里直接完成知识库问答和业务查询。这套路径学完你已经具备独立规划 Java LLM 应用架构的能力了。建议先收藏再按本文的章节逐一实践。
返回列表