目录Advisors自定义 AI 中间件《Spring AI 实战系列》完整目录 入门篇已完结 · 建议按顺序学习 进阶篇更新中️ 学习路径建议一、什么是 Advisors1.1 生活中的类比1.2 Advisors 能做什么二、工作原理2.1 执行流程2.2 核心接口2.3 顺序规则三、内置 Advisors3.1 常用内置 Advisors3.2 使用内置 Advisors3.3 配置 Advisor 参数四、自定义 Advisors4.1 日志记录 Advisor4.2 安全检查 Advisor4.3 对话记忆 Advisor4.4 重试机制 Advisor五、实战案例5.1 组合多个 Advisors5.2 带参数的 Advisor六、系列预告本篇小结系列回顾 参考资料 收藏关注持续更新Advisors自定义 AI 中间件系列说明本文为《Spring AI 实战系列 入门篇》第 5 篇前置知识完成第 1-4 篇预计阅读时间15 分钟《Spring AI 实战系列》完整目录 学习不迷路系列持续更新中点击链接直达各篇 入门篇已完结 · 建议按顺序学习篇目标题核心内容第 1 篇✅核心概念与快速上手Model / Prompt / Embedding 第一个项目第 2 篇✅Tool Calling让 AI 调用外部函数Tool声明式 编程式工具定义第 3 篇✅VectorStore RAG构建私有知识库向量数据库集成 文档检索第 4 篇✅结构化输出AI 结果映射为 POJOBeanOutputConverter第 5 篇✅Advisors自定义 AI 中间件拦截器链 对话记忆第 6 篇✅国产模型集成指南通义千问 / 文心一言 / 智谱 GLM 进阶篇更新中篇目标题核心内容进 1✅智能客服系统多轮对话 工具调用 人工兜底进 2✅企业知识库 RAG 管线多格式 ETL 混合检索RRF进 3AI Agent 自主规划ReAct 模式 多工具编排️ 学习路径建议Week 1-3 【入门篇】第1篇 → 第2篇 → 第3篇 → 第4篇 → 第5篇 → 第6篇 └→ 掌握 Spring AI 核心能力 Week 4-6 【进阶篇】智能客服 → 企业RAG → AI Agent └→ 实战企业级 AI 应用一、什么是 Advisors1.1 生活中的类比Advisors AI 应用的中间件 Web 开发中的 Filter 请求 → Filter1 → Filter2 → Controller → Filter2 → Filter1 → 响应 AI 开发中的 Advisor Prompt → Advisor1 → Advisor2 → LLM → Advisor2 → Advisor1 → 响应1.2 Advisors 能做什么功能说明日志记录记录请求与响应安全检查内容审核、敏感词过滤对话记忆维护多轮对话上下文重试机制失败自动重试监控统计请求次数、耗时统计RAG检索增强生成QuestionAnswerAdvisor二、工作原理2.1 执行流程┌────────────────────────────────────────────────────────────────────┐ │ Advisor 执行链 │ ├────────────────────────────────────────────────────────────────────┤ │ │ │ 用户请求 │ │ ↓ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ Advisor1 (order0, LOW) │ │ │ │ • 处理请求 │ │ │ │ • 可修改 Prompt │ │ │ │ • 调用下一个 → │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ Advisor2 (order100) │ │ │ │ • 处理请求 │ │ │ │ • 可修改 Prompt │ │ │ │ • 调用下一个 → │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ LLM最后一个环节实际调用 AI │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ 响应 ← Advisor2处理响应← Advisor1处理响应← 用户 │ │ │ └────────────────────────────────────────────────────────────────────┘2.2 核心接口packageorg.springframework.ai.chat.client.advisor.api;publicinterfaceCallAdvisorextendsAdvisor{/** Advisor 名称 */StringgetName();/** 执行顺序值越小越先执行 */intgetOrder();/** 处理请求 */ChatClientResponseadviseCall(ChatClientRequestrequest,CallAdvisorChainchain);}// 拦截器链publicinterfaceCallAdvisorChain{ChatClientResponsenextCall(ChatClientRequestrequest);}2.3 顺序规则┌────────────────────────────────────────┐ │ 执行顺序说明 │ ├────────────────────────────────────────┤ │ │ │ Integer.MIN_VALUE → HIGHEST_PRECEDENCE │ │ │ │ ┌─────────────────────────────┐ │ │ │ Advisor A (order 0) │ ← 先执行 │ │ └→ 修改请求 │ │ │ │ 调用下一个 │ │ │ │ ←─ 处理响应最后返回 │ │ │ └─────────────────────────────┘ │ │ ↓ │ │ ┌─────────────────────────────┐ │ │ │ Advisor B (order 100) │ │ │ │ └→ 修改请求 │ │ │ │ 调用下一个 │ │ │ │ ←─ 处理响应 │ │ │ └─────────────────────────────┘ │ │ ↓ │ │ ┌─────────────────────────────┐ │ │ │ LLM系统内置最后执行 │ │ │ └─────────────────────────────┘ │ │ │ │ Integer.MAX_VALUE → LOWEST_PRECEDENCE │ │ │ └────────────────────────────────────────┘三、内置 Advisors3.1 常用内置 AdvisorsAdvisor功能QuestionAnswerAdvisorRAG 检索增强ReReadingAdvisor重新阅读问题提升准确性LoggerAdvisor日志记录MemoryPreservationAdvisor记忆保留3.2 使用内置 AdvisorsRestControllerpublicclassAdvisorController{privatefinalChatClientchatClient;privatefinalVectorStorevectorStore;publicAdvisorController(ChatClient.Builderbuilder,VectorStorevectorStore){this.chatClientbuilder.build();this.vectorStorevectorStore;}GetMapping(/rag)publicStringragAsk(RequestParamStringquestion){returnchatClient.prompt().user(question).advisors(newQuestionAnswerAdvisor(vectorStore)// RAG Advisor).call().content();}GetMapping(/log)publicStringlogAsk(RequestParamStringquestion){returnchatClient.prompt().user(question).advisors(newLoggerAdvisor()// 日志 Advisor).call().content();}}3.3 配置 Advisor 参数// 传入配置chatClient.prompt().user(question).advisors(newQuestionAnswerAdvisor(vectorStore,SearchRequest.builder().topK(5).similarityThreshold(0.8).build())).call().content();四、自定义 Advisors4.1 日志记录 Advisorpackagecom.example.demo.advisor;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.ai.chat.client.advisor.api.Advisor;importorg.springframework.ai.chat.client.advisor.api.CallAdvisor;importorg.springframework.ai.chat.client.advisor.api.CallAdvisorChain;importorg.springframework.ai.chat.client.ChatClientRequest;importorg.springframework.ai.chat.client.ChatClientResponse;importorg.springframework.core.Ordered;publicclassLoggingAdvisorimplementsCallAdvisor{privatestaticfinalLoggerlogLoggerFactory.getLogger(LoggingAdvisor.class);OverridepublicStringgetName(){returnlogging-advisor;}OverridepublicintgetOrder(){returnOrdered.LOWEST_PRECEDENCE-100;// 较低优先级}OverridepublicChatClientResponseadviseCall(ChatClientRequestrequest,CallAdvisorChainchain){// 记录请求log.info( AI 请求 );log.info(用户消息: {},request.prompt().getUserMessage().getText());// 继续调用链ChatClientResponseresponsechain.nextCall(request);// 记录响应log.info( AI 响应 );log.info(响应内容: {},response.chatResponse().getResult().getOutput().getText());returnresponse;}}4.2 安全检查 Advisorpackagecom.example.demo.advisor;importorg.springframework.ai.chat.client.advisor.api.Advisor;importorg.springframework.ai.chat.client.advisor.api.CallAdvisor;importorg.springframework.ai.chat.client.advisor.api.CallAdvisorChain;importorg.springframework.ai.chat.client.ChatClientRequest;importorg.springframework.ai.chat.client.ChatClientResponse;importorg.springframework.core.Ordered;importjava.util.List;publicclassSecurityAdvisorimplementsCallAdvisor{privatestaticfinalListStringSENSITIVE_WORDSList.of(密码,银行卡,身份证,信用卡,验证码,手机号);OverridepublicStringgetName(){returnsecurity-advisor;}OverridepublicintgetOrder(){returnOrdered.HIGHEST_PRECEDENCE100;// 较高优先级}OverridepublicChatClientResponseadviseCall(ChatClientRequestrequest,CallAdvisorChainchain){// 获取用户输入StringuserTextrequest.prompt().getUserMessage().getText();// 检查敏感词for(Stringword:SENSITIVE_WORDS){if(userText.contains(word)){thrownewSecurityException(包含敏感词: word);}}// 继续调用链returnchain.nextCall(request);}}4.3 对话记忆 AdvisorpublicclassSimpleMemoryAdvisorimplementsCallAdvisor{privatefinalListMessagehistorynewArrayList();OverridepublicStringgetName(){returnsimple-memory;}OverridepublicintgetOrder(){return0;}OverridepublicChatClientRequestadviseCall(ChatClientRequestrequest,CallAdvisorChainchain){// 添加历史消息到请求ChatClientRequestmodifiedRequestnewChatClientRequest(request.user(),MessageUtils.appendMessages(history,MessageUtils.fromUser(request.user())),request.options());// 继续执行ChatClientResponseresponsechain.nextCall(modifiedRequest);// 记录对话历史history.add(MessageUtils.fromAssistant(response.result().getText()));// 限制历史长度if(history.size()20){history.subList(0,10).clear();}returnresponse;}OverridepublicFluxChatClientResponseadviseStream(FluxChatClientResponseflux,StreamAdvisorChainchain){returnchain.next(flux);}}4.4 重试机制 AdvisorpublicclassRetryAdvisorimplementsCallAdvisor{privatefinalintmaxRetries;privatefinallongretryDelayMs;publicRetryAdvisor(intmaxRetries,longretryDelayMs){this.maxRetriesmaxRetries;this.retryDelayMsretryDelayMs;}OverridepublicStringgetName(){returnretry-advisor;}OverridepublicintgetOrder(){returnInteger.MAX_VALUE;// 最后执行}OverridepublicChatClientRequestadviseCall(ChatClientRequestrequest,CallAdvisorChainchain){ExceptionlastExceptionnull;for(inti0;imaxRetries;i){try{returnchain.nextCall(request);}catch(Exceptione){lastExceptione;if(imaxRetries-1){try{Thread.sleep(retryDelayMs);}catch(InterruptedExceptionie){Thread.currentThread().interrupt();}}}}thrownewRuntimeException(重试失败,lastException);}OverridepublicFluxChatClientResponseadviseStream(FluxChatClientResponseflux,StreamAdvisorChainchain){returnchain.next(flux);}}五、实战案例5.1 组合多个 AdvisorsRestControllerRequestMapping(/ai)publicclassAdvisorDemoController{privatefinalChatClientchatClient;publicAdvisorDemoController(ChatClient.Builderbuilder){this.chatClientbuilder.build();}GetMapping(/secure-chat)publicStringsecureChat(RequestParamStringquestion){returnchatClient.prompt().user(question).advisors(newSecurityAdvisor(),// 1. 安全检查最先newLoggingAdvisor(),// 2. 日志记录newRetryAdvisor(3,1000)// 3. 重试机制最后).call().content();}GetMapping(/memory-chat)publicStringmemoryChat(RequestParamStringquestion){returnchatClient.prompt().user(question).advisors(newSimpleMemoryAdvisor()// 对话记忆).call().content();}}5.2 带参数的 AdvisorConfigurationpublicclassAdvisorConfig{BeanpublicCallAdvisorcustomLoggerAdvisor(){returnnewCallAdvisor(){OverridepublicStringgetName(){returncustom-logger;}OverridepublicintgetOrder(){return0;}OverridepublicChatClientRequestadviseCall(ChatClientRequestrequest,CallAdvisorChainchain){System.out.println( 请求: request.user());ChatClientResponseresponsechain.nextCall(request);System.out.println( 响应: response.result().getText());returnresponse;}OverridepublicFluxChatClientResponseadviseStream(FluxChatClientResponseflux,StreamAdvisorChainchain){returnchain.nextStream(flux);}};}}六、系列预告本篇小结✅ 理解了 Advisors 原理与执行链✅ 掌握了内置 Advisors 用法✅ 学会了自定义 Advisors系列回顾好消息入门篇全部 6 篇已完结进阶篇持续更新中 入门篇完结 —— 恭喜你已完成第 5 篇推荐学习路径第1篇 → 第2篇 → 第3篇 → 第4篇 → 第5篇本文✅→ 第6篇国产模型·终篇 参考资料Spring AI Advisors 文档https://docs.spring.io/spring-ai/reference/api/advisors.html引用说明本文核心概念与技术描述参考自 Spring AI 官方文档https://docs.spring.io/spring-ai/reference/Advisors 相关内容来自官方 Advisors API 章节。 收藏关注持续更新如果觉得有帮助请⭐收藏本文—— 方便后续查阅随时回顾核心概念关注同名公众号—— 点击菜单「获取源码」获取完整代码Gitee 仓库系列更新不迷路下篇推荐第 6 篇 · 国产模型集成指南终篇