乐于分享
好东西不私藏

Javaer的AI学习之路——Spring AI 入门:(7)Advisors 切面拦截

Javaer的AI学习之路——Spring AI 入门:(7)Advisors 切面拦截

在构建真实的 AI 应用时,需要在不修改核心业务逻辑的情况下,为 AI 交互添加各种横切能力——例如记录每一次请求的日志用于调试分析、自动将对话历史注入上下文实现多轮聊天、对用户输入进行敏感词过滤以确保内容合规等。如果将这些逻辑一股脑地塞进业务代码,势必导致代码臃肿、难以维护、无法复用。

Spring AI 的 Advisors 机制,正是为了解决这些问题而设计的。它借鉴了 Spring AOP 和装饰器模式的设计思想,提供了一套可插拔、可组合的拦截器框架,让你能够在 AI 调用链中优雅地插入自定义逻辑。

7.1 什么是 Advisor

7.1.1 从 AOP 到 Advisor

Spring AOP 通过切面(Aspect)将日志、事务、安全等横切关注点从业务逻辑中剥离出来,实现了关注点的分离。Spring AI 的 Advisor 机制沿用了这一设计思想,并针对 AI 交互场景做了专门优化。

简单来说,Advisor 就是一个拦截器——在将请求发送给 AI 模型之前和执行模型返回之后,Advisor 都会有机会介入,对请求进行预处理或对响应进行后处理。

业务代码 → [Advisor 链] → AI 模型

类似的拦截器设计在其他技术栈中也广泛存在。例如 Servlet 中的 Filter、Spring MVC 中的 Interceptor,以及 Spring AOP 的 @Around 通知——它们都基于责任链模式,允许在请求处理的前后插入自定义逻辑。

💡 类比理解:Advisor 之于 Spring AI,就像 Filter 之于 Servlet、Interceptor 之于 Spring MVC——都是横切关注点的优雅解决方案。

7.1.2 为什么需要 Advisor

在实际开发中,我们经常遇到以下需求:

  • 记录日志:记录每次 AI 请求的输入和输出,便于调试和审计

  • 对话记忆:将历史对话自动注入当前请求,实现多轮对话能力

  • 内容安全:在请求发送前过滤敏感词,在响应返回前屏蔽不当内容

  • 限流控制:防止 API 调用过于频繁导致费用超支

  • 缓存处理:相同的问题直接返回缓存结果,减少 API 调用和成本

  • RAG 检索增强:在请求发送前从向量数据库检索相关文档并注入上下文

Spring AI 的 Advisor 机制就是为了统一应对这些横切需求而设计的。它让你可以:

  • 解耦:将通用 AI 模式从业务逻辑中剥离

  • 复用:一次编写,多处复用

  • 组合:多个 Advisor 可按需组合,形成处理链

7.2 核心接口体系

7.2.1 Advisor 顶层接口

Spring AI 的 Advisor 接口设计遵循了清晰的分层结构,位于 org.springframework.ai.chat.client.advisor.api 包中。下面是完整的接口继承关系。

接口继承关系:

Advisor(顶层接口:定义 getName() 和 getOrder())
 │
 ├── CallAdvisor(同步/非流式拦截器)       ← 本章重点
 │       │
 │       └── CallAroundAdvisor(扩展:支持前置/后置处理,是 CallAdvisor 的增强形式)
 │
 └── StreamAdvisor(异步/流式拦截器)
         │
         └── StreamAroundAdvisor(扩展:支持流式场景的前置/后置处理)

Advisor 是所有 Advisor 的基础接口,定义了两个核心方法:

publicinterfaceAdvisorextendsOrdered {
/**
     * 返回顾问的唯一标识名称
     */

    String getName();

// 继承自 Ordered,通过 getOrder() 控制执行顺序
}
  • getName():返回顾问的唯一标识名称,便于调试和日志追踪

  • getOrder():继承自 Ordered 接口,用于控制多个 Advisor 的执行顺序,数值越小优先级越高

⚠️ 关键提醒:所有自定义 Advisor 都必须实现 getName() 方法,框架依赖这个标识进行顾问管理。

7.2.2 CallAdvisor(同步拦截器)

CallAdvisor 是最常用的 Advisor 接口,适用于普通的“发一条消息 → 等待完整回复”的同步调用场景。

publicinterfaceCallAdvisorextendsAdvisor {
/**
     * 处理 AI 请求的核心方法
     * 
     * @param request 客户端请求对象,包含 prompt、options 等数据
     * @param chain   责任链对象,用于调用下一个 Advisor
     * @return AI 响应结果
     */

    ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain);
}

adviseCall 方法是实现自定义逻辑的核心入口。它的参数包括当前请求对象和责任链对象——你的代码可以在调用 chain.nextCall(request)之前执行预处理(如修改 Prompt、添加上下文、记录时间戳等),在 chain.nextCall(request)返回之后执行后处理(如记录响应日志、计算耗时等)。

提示:在 Spring AI 的早期版本中,CallAroundAdvisor 接口提供了更丰富的生命周期方法(如 before 和 after),但在较新的 API 设计中,推荐直接使用 CallAdvisor 并通过 adviseCall 方法实现完整的环绕增强逻辑。

7.3 运行机制

7.3.1 核心数据结构

在编写 Advisor 时有几个核心数据对象:

  • ChatClientRequest:请求对象,包含了准备发送给 AI 模型的 Prompt、参数配置(如 temperature、maxTokens)等信息。Advisor 可以读取并修改这个对象,例如在 Prompt 中添加额外的系统消息。

  • ChatClientResponse:响应对象,包含了 AI 模型返回的结果。Advisor 可以对响应进行校验、过滤或补充信息。

  • CallAdvisorChain:责任链对象,通过调用它的 nextCall(request) 方法将处理权移交给链条中的下一个 Advisor。

7.3.2 请求/响应处理链

Advisors 的执行遵循责任链模式。当多个 Advisor 被注册到 ChatClient 时,它们会形成一个栈式处理链(Stack-based Chain) ,这个机制和 Spring AOP 的环绕通知内部原理基本一致。

整个处理流程有两个阶段:

┌─────────────────────────────────────────────────────────────────┐
│  请求阶段(请求从链顶流向链底)                                    │
│  Advisor 1(order=1)→ Advisor 2(order=2)→ ... → AI 模型       │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│  响应阶段(响应从链底流回链顶)                                    │
│  AI 模型 → ... → Advisor 2(order=2)→ Advisor 1(order=1)       │
└─────────────────────────────────────────────────────────────────┘
  • 请求阶段:从链顶到链底,order 值越小的 Advisor 越先执行

  • 响应阶段:从链底到链顶,order 值越小的 Advisor 反而越后执行

  • 最后一个 Advisor:由框架自动添加,负责实际调用 LLM

这种栈式结构的一个重要特点是,请求阶段和响应阶段的执行顺序是相反的。例如,假设我们有三个 Advisor 按照 order 值 1→2→3 的顺序排列,那么请求阶段会依次经过 Advisor 1、Advisor 2、Advisor 3 后再到达 AI 模型;而当模型返回响应后,响应会先经过 Advisor 3 处理,再依次经过 Advisor 2、Advisor 1 后返回到业务代码。这种“先进后出”的顺序,让前后对称的逻辑(如记录请求时间并计算耗时)可以优雅地实现。

7.3.3 执行顺序实践

在真实项目中,通常需要同时使用多个 Advisor,例如同时启用日志记录、对话记忆和敏感词过滤。多个 Advisor 的执行顺序由 getOrder() 方法的返回值控制。

配置多个 Advisor:

@Configuration
publicclassAdvisorConfig {

@Bean
public ChatClient chatClient(ChatModel chatModel) {
// 执行顺序:
// 1. 日志记录(order=100)→ 2. 记忆管理(order=200)→ 3. 敏感词过滤(order=300)→ AI 模型
return ChatClient.builder(chatModel)
                .advisors(
newSimpleLoggerAdvisor(100),           // order=100,最先执行
newMessageChatMemoryAdvisor(memory, "conv-123"200),  // order=200
newSensitiveWordAdvisor(300)           // order=300,最后执行
                )
                .build();
    }
}

多个 Advisor 的执行顺序遵循以下规则:

  • 数值越小,优先级越高,越先执行

  • **最后一个 Advisor(由框架自动添加)**负责调用 LLM
  • 建议使用 Advisor.DEFAULT_CHAT_MEMORY_PRECEDENCE_ORDER 等常量作为参考基准

  • 合法范围在 Integer.MIN_VALUE 到 Integer.MAX_VALUE 之间

以下是执行顺序示例:

请求阶段:日志(100) → 记忆(200) → 敏感词(300) → AI 模型
响应阶段:AI 模型 → 敏感词(300) → 记忆(200) → 日志(100)

⚠️ 关键要点:请求阶段的顺序和响应阶段的顺序正好相反。如果日志顾问先于敏感词顾问处理请求,那么在响应阶段,敏感词顾问会先于日志顾问处理响应——这也是为什么日志顾问能记录完整的响应内容。

执行顺序最佳实践:

Advisor类型
推荐 order
说明
日志记录
100~200
尽早记录原始请求,最晚记录最终响应
内容审核/敏感词过滤
300~400
在请求发送前做安全校验,在响应返回时做脱敏
对话记忆
500~600
在安全过滤之后加载历史,避免将敏感历史写入记忆
RAG 检索
700~800
通常在历史注入之后执行
业务自定义逻辑
900~1000
最后执行,只处理经过其他顾问处理后的数据

内置的一些 order 常量参考:

常量
说明
Ordered.HIGHEST_PRECEDENCE-2147483648
最高优先级
Advisor.DEFAULT_CHAT_MEMORY_PRECEDENCE_ORDER
500
官方默认记忆顾问的基准值
Ordered.LOWEST_PRECEDENCE2147483647
最低优先级

7.4 Advisor分类

Spring AI 提供了一些内置的 Advisor,覆盖了日志记录、聊天记忆、RAG 检索等常见场景。

7.4.1 SimpleLoggerAdvisor:日志记录

SimpleLoggerAdvisor 是调试阶段的“利器”。它能够在每一次 AI 调用时,自动打印请求和响应的完整内容,帮助开发者快速了解 AI 模型的输入输出情况。

使用示例

@RestController
@RequestMapping("/advisor")
publicclassAdvisorDemoController {

privatefinal ChatClient chatClient;

publicAdvisorDemoController(ChatClient.Builder builder) {
this.chatClient = builder
                .defaultAdvisors(newSimpleLoggerAdvisor())  //添加日志
                .build();
    }

@GetMapping("/chat-with-log")
public String chat(@RequestParam String msg) {
return chatClient.prompt()
                .user(msg)
                .call()
                .content();
    }

}

调用接口后,控制台会输出类似以下的日志信息(需要将日志级别设置为 DEBUG):

2026-06-01T11:24:12.129+08:00 DEBUG 36908 --- [spring-ai-tutorial] [nio-8080-exec-2] o.s.a.c.c.advisor.SimpleLoggerAdvisor    : request: ChatClientRequest[prompt=Prompt{messages=[UserMessage{content='你好', metadata={messageType=USER}, messageType=USER}], modelOptions=OpenAiChatOptions: {"streamUsage":false,"model":"qwen3.6-plus","temperature":0.7}}, context={}]
2026-06-01T11:24:17.344+08:00 DEBUG 36908 --- [spring-ai-tutorial] [nio-8080-exec-2] o.s.a.c.c.advisor.SimpleLoggerAdvisor    : response: {
  "result" : {
    "metadata" : {
      "finishReason" : "STOP",
      "contentFilters" : [ ],
      "empty" : true
    },
    "output" : {
      "messageType" : "ASSISTANT",
      "metadata" : {
        "role" : "ASSISTANT",
        "messageType" : "ASSISTANT",
        "finishReason" : "STOP",
        "refusal" : "",
        "annotations" : [ { } ],
        "index" : 0,
        "id" : "chatcmpl-1d28f1fd-7c62-9731-b554-d2e68605ac39"
      },
      "toolCalls" : [ ],
      "media" : [ ],
      "text" : "你好!有什么我可以帮你的吗?"
    }
  },
  "metadata" : {
    "id" : "chatcmpl-1d28f1fd-7c62-9731-b554-d2e68605ac39",
    "model" : "qwen3.6-plus",
    "rateLimit" : {
      "requestsLimit" : null,
      "requestsRemaining" : null,
      "tokensLimit" : null,
      "tokensRemaining" : null,
      "requestsReset" : null,
      "tokensReset" : null
    },
    "usage" : {
      "promptTokens" : 11,
      "completionTokens" : 212,
      "totalTokens" : 223,
      "nativeUsage" : {
        "completion_tokens" : 212,
        "prompt_tokens" : 11,
        "total_tokens" : 223,
        "prompt_tokens_details" : { },
        "completion_tokens_details" : {
          "reasoning_tokens" : 199
        }
      }
    },
    "promptMetadata" : [ ],
    "empty" : false
  },
  "results" : [ {
    "metadata" : {
      "finishReason" : "STOP",
      "contentFilters" : [ ],
      "empty" : true
    },
    "output" : {
      "messageType" : "ASSISTANT",
      "metadata" : {
        "role" : "ASSISTANT",
        "messageType" : "ASSISTANT",
        "finishReason" : "STOP",
        "refusal" : "",
        "annotations" : [ { } ],
        "index" : 0,
        "id" : "chatcmpl-1d28f1fd-7c62-9731-b554-d2e68605ac39"
      },
      "toolCalls" : [ ],
      "media" : [ ],
      "text" : "你好!有什么我可以帮你的吗?"
    }
  } ]
}

一般以下场景可以使用

  • 开发阶段调试 Prompt 效果
  • 生产环境审计请求/响应(注意数据脱敏)
  • 排查 AI 调用异常问题

💡 提示:在生产环境中使用日志顾问时,应当注意对敏感信息(如用户个人信息)进行脱敏处理,避免日志泄露。

7.4.2 MessageChatMemoryAdvisor:对话记忆

默认情况下,AI 模型是无状态的——每次请求都是独立的,模型记不住你上一轮说了什么。MessageChatMemoryAdvisor 解决了这个问题,它能够自动保存和加载对话历史,并将历史消息以独立消息的形式插入到当前请求的 Prompt 中。

基本使用

@RestController
@RequestMapping("/advisor")
publicclassAdvisorDemoController {

privatefinal ChatClient chatClient;

publicAdvisorDemoController(ChatClient.Builder builder) {
// 创建内存存储仓库
InMemoryChatMemoryRepositoryrepository=newInMemoryChatMemoryRepository();
// 创建基于消息窗口的记忆实现,设置保留最近10条消息
ChatMemorychatMemory= MessageWindowChatMemory.builder()
                .maxMessages(5)  // 保留最近5条消息
                .chatMemoryRepository(repository)
                .build();
// 创建记忆顾问,指定记忆模块
MessageChatMemoryAdvisormemoryAdvisor= MessageChatMemoryAdvisor.builder(chatMemory)
                .build();
this.chatClient = builder
                .defaultAdvisors(newSimpleLoggerAdvisor(), memoryAdvisor)  // 添加日志顾问和记忆顾问
                .build();
    }

@GetMapping("/chat-with-memory")
public String chatWithMemory(@RequestParam String msg,
@RequestParam(required = false, defaultValue = "user001") String sessionId)
 {
return chatClient.prompt()
                .user(msg)
                .advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, sessionId))  // 动态添加sessionId
                .call()
                .content();
    }

关键对象

对向
说明
InMemoryChatMemoryRepository
会话记忆的内存存储仓库
MessageWindowChatMemory
基于窗口的内存记忆模块,参数有最大窗口,记忆仓库
MessageChatMemoryAdvisor
创建记忆Advisor,执行记忆模块

然后我们在使用时,注意动态的绑定用户的sessionId,从而将不同用户数据分开。

7.4.3 其他常用 Advisor

还有一些其他的可以参考

Advisor
作用
适用场景
QuestionAnswerAdvisor
自动执行 RAG 流程:向量检索 → 文档注入 → AI 生成
私有知识问答
SafeGuardAdvisor
屏蔽敏感词,拦截含有违规内容的请求
内容安全审核
ToolCallAdvisor
管理工具调用的执行循环
工具调用流程控制
VectorStoreChatMemoryAdvisor
使用向量数据库存储对话历史
长会话、高并发场景

7.4.4 自定义 Advisor

当内置 Advisor 无法满足需求时,还可以开发自己的 Advisor。比如以敏感词过滤为例,实现一个完整的自定义 Advisor。

实现一个自定义 Advisor 只需要三步:

  1. 创建类实现 CallAdvisor 接口

  2. 重写 getName() 和 getOrder() 方法

  3. 在 adviseCall 方法中实现前置/后置逻辑

完整代码示例:

package com.springai.guide.advisor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import org.springframework.ai.chat.client.advisor.api.CallAdvisor;
import org.springframework.ai.chat.client.advisor.api.CallAdvisorChain;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.core.Ordered;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.Generation;
import org.springframework.ai.chat.prompt.Prompt;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 敏感词过滤顾问
 * 在请求发送前检查用户输入,若包含敏感词则阻止请求;在响应返回后检查模型输出,若包含敏感词则脱敏处理。
 */

publicclassSensitiveWordAdvisorimplementsCallAdvisor {

privatestaticfinalLoggerlog= LoggerFactory.getLogger(SensitiveWordAdvisor.class);

// 敏感词列表(实际使用时可以从配置中心或数据库动态加载)
privatestaticfinal List<String> SENSITIVE_WORDS = List.of("密码""信用卡号""身份证号");

// 脱敏字符
privatestaticfinalStringMASK="***";

// 执行顺序,值越小越靠前
privateintorder= Ordered.HIGHEST_PRECEDENCE + 100;

publicSensitiveWordAdvisor() {}

publicSensitiveWordAdvisor(int order) {
this.order = order;
    }

@Override
public ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {
// ========== 前置处理:检查用户输入 ==========
StringuserInput= extractUserText(request);

// 检查是否包含敏感词
StringfoundWord= containsSensitiveWord(userInput);
if (foundWord != null) {
            log.warn("敏感词过滤: 检测到敏感词 [{}], 请求被阻止", foundWord);

// 直接抛出异常或返回空响应来阻止请求
thrownewIllegalArgumentException("输入包含敏感信息: " + foundWord + ", 请修改后重试");
        }

// ========== 调用下一个顾问(最终到达 AI 模型) ==========
ChatClientResponseresponse= chain.nextCall(request);

// ========== 后置处理:对模型输出进行脱敏检查和记录 ==========
StringaiResponse= extractContentFromResponse(response);
StringsafeResponse= maskSensitiveWords(aiResponse);

if (!safeResponse.equals(aiResponse)) {
            log.info("敏感词过滤: 检测到响应中包含敏感词");
            log.debug("原始响应: {}", aiResponse);
            log.debug("脱敏后响应: {}", safeResponse);
        }

return response;
    }

/**
     * 检查文本是否包含敏感词,返回第一个匹配的敏感词
     */

private String containsSensitiveWord(String text) {
return SENSITIVE_WORDS.stream()
                .filter(text::contains)
                .findFirst()
                .orElse(null);
    }

/**
     * 从 ChatClientResponse 中提取响应内容
     */

private String extractContentFromResponse(ChatClientResponse response) {
ChatResponsechatResponse= response.chatResponse();
if (chatResponse != null && !chatResponse.getResults().isEmpty()) {
return chatResponse.getResults().getFirst().getOutput().getText();
        }
return"";
    }

/**
     * 对文本中的敏感词进行脱敏
     */

private String maskSensitiveWords(String text) {
Stringresult= text;
for (String word : SENSITIVE_WORDS) {
            result = result.replace(word, MASK);
        }
return result;
    }

/**
     * 从 ChatClientRequest 中提取用户输入文本
     */

private String extractUserText(ChatClientRequest request) {
Promptprompt= request.prompt();
// 从 Prompt 中获取 UserMessage 并拼接文本
return prompt.getInstructions().stream()
                .filter(msg -> msg instanceof UserMessage)
                .map(msg -> ((UserMessage) msg).getText())
                .collect(Collectors.joining(" "));
    }

@Override
public String getName() {
return"sensitiveWordAdvisor";
    }

@Override
publicintgetOrder() {
returnthis.order;
    }
}

关键部分包括:

  • 前置处理extractUserText() 从请求中提取用户输入,调用 containsSensitiveWord() 检查是否包含敏感词。如果匹配,立即返回错误响应,阻止后续调用链。

  • 链接调用chain.nextCall(request) 是责任链的精髓,它将请求传递给下一个 Advisor。如果这是链条中的最后一个 Advisor,框架会负责调用 AI 模型。

  • 后置处理:AI 模型返回响应后,调用 maskSensitiveWords() 对输出内容中的敏感词进行脱敏处理,然后构建新的响应对象返回。

7.5 实战:构建带完整增强的智能问答

将本章内容整合起来,做一个综合示例:一个同时具备日志记录、对话记忆和敏感词过滤能力的智能问答接口。

完整代码实现:

@RestController
@RequestMapping("/api/advisor-demo")
publicclassAdvisorCompleteDemoController {

privatefinal ChatClient chatClient;

publicAdvisorDemoController(ChatClient.Builder builder) {
// 创建内存存储仓库
InMemoryChatMemoryRepositoryrepository=newInMemoryChatMemoryRepository();
// 创建基于消息窗口的记忆实现,设置保留最近10条消息
ChatMemorychatMemory= MessageWindowChatMemory.builder()
                .maxMessages(5)  // 保留最近5条消息
                .chatMemoryRepository(repository)
                .build();
// 创建记忆顾问,指定记忆模块
MessageChatMemoryAdvisormemoryAdvisor= MessageChatMemoryAdvisor.builder(chatMemory)
                .order(200)
                .build();
this.chatClient = builder
// 执行顺序:日志(100) → 记忆(200) → 敏感词(300) → AI 模型
                .defaultAdvisors(newSimpleLoggerAdvisor(100), memoryAdvisor, newSensitiveWordAdvisor(300))  // 添加日志顾问和记忆顾问
                .build();
    }

@GetMapping("/chat")
public ResponseEntity<ApiResponse<String>> chat(@RequestParam String msg) {
longstartTime= System.currentTimeMillis();
try {
Stringresponse= chatClient.prompt()
                    .user(msg)
                    .call()
                    .content();
longduration= System.currentTimeMillis() - startTime;
return ResponseEntity.ok(ApiResponse.success(response, duration));
        } catch (Exception e) {
// 敏感词过滤等场景可能抛出异常
return ResponseEntity.badRequest()
                    .body(ApiResponse.error(e.getMessage()));
        }
    }

}

响应封装改为:

// ========== 响应封装 ==========
publicrecordApiResponse<T>(
int code,
    String message,
    T data,
long timestamp,
long duration
) {
publicstatic <T> ApiResponse<T> success(T data) {
returnnewApiResponse<>(200"success", data, System.currentTimeMillis(), 0);
    }

publicstatic <T> ApiResponse<T> error(String message) {
returnnewApiResponse<>(500, message, null, System.currentTimeMillis(), 0);
    }

publicstatic <T> ApiResponse<T> success(T data, long duration) {
returnnewApiResponse<>(200"success", data, System.currentTimeMillis(),  duration);
    }

publicstatic <T> ApiResponse<T> error(int code, String message) {
returnnewApiResponse<>(code, message, null, System.currentTimeMillis(), 0);
    }
}

测试效果如下:

# 正常问答
curl "http://localhost:8080/api/advisor-demo/chat?msg=你好,请介绍一下Spring"
# 正常返回

# 测试敏感词过滤
curl "http://localhost:8080/api/advisor-demo/chat?msg=我的密码是123456"
# 返回:输入包含敏感信息,请修改后重试

# 测试记忆能力
curl "http://localhost:8080/api/advisor-demo/chat?msg=我叫张三"
curl "http://localhost:8080/api/advisor-demo/chat?msg=我叫什么名字?"
# AI 能够记住之前输入的名字

7.6 常见误区与最佳实践

7.6.1 ❌ 误区一:忘记调用 chain.nextCall()

自定义的Advisor没有调用 chain.nextCall()

// ❌ 错误示例
public ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {
    preProcess(request);
return ChatClientResponse.from(...).build();  // 没有调用 chain.nextCall(),后续Advisor和 AI 模型都不会执行!
}

正确做法:必须调用 chain.nextCall(request),并返回其响应结果:

public ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {
    request = preProcess(request);                  // 前置处理
ChatClientResponseresponse= chain.nextCall(request);  // 必须调用!
return postProcess(response);                   // 后置处理
}

7.6.2 ✅ 最佳实践速查表

场景
建议
单一职责每个<font style="color:rgb(1, 1, 1);">Advisor</font> 只干一件事(比如只记录日志,或只处理记忆),不要在一个 Advisor 里写几千行代码。
order 取值
使用常量基准值,预留间隔方便插入新顾问
响应修改
使用 ChatClientResponse.from(response).content(newContent).build() 构建新响应对象
请求阻止
直接返回错误响应,不调用 chain.nextCall()
会话隔离
始终使用显式 conversationId,不同用户使用不同 ID
调试辅助
通过 Advisor 的 getName() 返回有意义的标识,便于日志定位
数据共享
使用 AdvisorContext 在多个 Advisor 之间传递数据(例如:请求 ID、权限信息等)
性能考量
尽量减少重复计算,考虑将计算结果缓存到 AdvisorContext 中,供下游顾问复用
异常处理
对 AI 模型调用失败、网络超时等异常情况进行妥善处理,避免影响用户体验

7.7 本章小结

在本章中,我们全面深入地学习了 Spring AI 的 Advisor 机制:

  • 核心概念:Advisor 是基于责任链模式的拦截器框架,用于为 AI 交互添加横切关注点,类似于 Spring AOP 但专为 AI 场景优化

  • 工作原理:形成栈式处理链,请求阶段从高优先级到低优先级执行,响应阶段顺序相反

  • 接口体系Advisor(顶层)→ CallAdvisor(同步拦截,最常用)→ 自定义实现

  • 内置 Advisor

    • SimpleLoggerAdvisor:自动打印请求和响应日志

    • MessageChatMemoryAdvisor:自动管理多轮对话历史(必须显式指定 conversationId

    • QuestionAnswerAdvisorSafeGuardAdvisorToolCallAdvisor 等

  • 自定义开发:实现 CallAdvisor 接口,在 adviseCall 中编写前/后置逻辑

  • 综合实战:构建了集日志、记忆、敏感词过滤于一体的完整示例

Advisor 机制的强大之处在于它的可插拔性可组合性。你可以在项目中灵活组合官方提供的 Advisor,也可以自定义实现符合业务需求的专属Advisor。掌握了 Advisor 机制,你将能够构建更加健壮、功能丰富的 AI 应用。

下一章,将系统学习 Spring AI 的聊天记忆机制——包括记忆存储策略、记忆窗口管理以及如何将记忆持久化到数据库。

参考来源

  • Spring AI 官方文档:Advisors Framework
  • Supercharging Your AI Applications with Spring AI Advisors

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-06-10 12:11:57 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/732659.html
  2. 运行时间 : 0.186383s [ 吞吐率:5.37req/s ] 内存消耗:4,843.93kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=bf5499c026587d3997e457a2c83e0a9a
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000876s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000879s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000349s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000255s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000466s ]
  6. SELECT * FROM `set` [ RunTime:0.000200s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000615s ]
  8. SELECT * FROM `article` WHERE `id` = 732659 LIMIT 1 [ RunTime:0.000701s ]
  9. UPDATE `article` SET `lasttime` = 1781064717 WHERE `id` = 732659 [ RunTime:0.018227s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000266s ]
  11. SELECT * FROM `article` WHERE `id` < 732659 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000456s ]
  12. SELECT * FROM `article` WHERE `id` > 732659 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000413s ]
  13. SELECT * FROM `article` WHERE `id` < 732659 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000875s ]
  14. SELECT * FROM `article` WHERE `id` < 732659 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001872s ]
  15. SELECT * FROM `article` WHERE `id` < 732659 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.004235s ]
0.187910s