You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+GraphQL服务中Logback Access无法捕获响应内容排查

问题:Spring Boot + Spring for GraphQL中Logback Access无法捕获响应内容

我们正在使用Spring Boot和Spring for GraphQL开发新服务,希望启用Logback Access日志以捕获请求和响应的头信息及内容。已完成相关配置,但目前仅能捕获请求头与请求内容,响应内容始终为空。

已配置信息

application.yaml

logback:
  access:
    enabled: true
    config: classpath:logback/logback-access.xml
    useServerPortInsteadOfLocalPort: true
    tee-filter:
      enabled: true
  tomcat:
    enableRequestAttributes: true

logback-access.xml

<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%fullRequest%n%n%fullResponse</pattern>
    </encoder>
</appender>
<appender-ref ref="CONSOLE"/>
</configuration>

TeeFilter配置(已尝试order取值[-1,0,1,9999,-9999])

@Bean
public FilterRegistrationBean<TeeFilter> someFilterRegistration() {
    FilterRegistrationBean<TeeFilter> registrationBean = new FilterRegistrationBean<>(new TeeFilter());
    registrationBean.addUrlPatterns("/*");
    registrationBean.setName("TeeFilter");
    registrationBean.setOrder(-1);

    return registrationBean;
}

控制台输出示例显示请求内容正常,但响应无内容。此配置在其他Spring Boot REST服务中可正常捕获响应内容,请问该问题是否与Spring for GraphQL或Graphql for Java相关?


解决方案

这个问题确实和Spring for GraphQL的响应处理机制直接相关:

  • 普通Spring Boot REST服务的响应会经过Spring MVC完整的Filter链处理,TeeFilter能在响应流提交前捕获内容;
  • 而Spring for GraphQL的GraphQlHttpHandler是直接向Servlet响应流写入内容,绕过了Filter链中后续的响应拦截逻辑,导致TeeFilter无法获取到响应数据。

可以通过以下两种方式解决:

方式一:使用ContentCachingResponseWrapper包装响应

自定义Filter在请求进入GraphQL处理器前包装响应,确保响应内容被缓存,让TeeFilter能捕获到:

  1. 实现自定义Filter:
import org.springframework.web.filter.OncePerRequestFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.util.ContentCachingResponseWrapper;

import java.io.IOException;

public class ResponseCachingFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
        try {
            filterChain.doFilter(request, wrappedResponse);
        } finally {
            wrappedResponse.copyBodyToResponse();
        }
    }
}
  1. 注册该Filter,设置比TeeFilter更高的优先级:
@Bean
public FilterRegistrationBean<ResponseCachingFilter> responseCachingFilterRegistration() {
    FilterRegistrationBean<ResponseCachingFilter> registrationBean = new FilterRegistrationBean<>(new ResponseCachingFilter());
    registrationBean.addUrlPatterns("/*");
    registrationBean.setName("ResponseCachingFilter");
    registrationBean.setOrder(-2); // 优先级高于TeeFilter的-1
    return registrationBean;
}

方式二:使用Spring for GraphQL拦截器记录响应

直接通过GraphQL原生拦截器捕获响应内容,配合Logback日志输出:

  1. 实现WebGraphQlInterceptor:
import org.springframework.graphql.server.WebGraphQlInterceptor;
import org.springframework.graphql.server.WebGraphQlRequest;
import org.springframework.graphql.server.WebGraphQlResponse;
import reactor.core.publisher.Mono;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GraphQlResponseLoggingInterceptor implements WebGraphQlInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(GraphQlResponseLoggingInterceptor.class);

    @Override
    public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
        return chain.next(request)
                .doOnNext(response -> {
                    String responseContent = response.toExecutionResult().toString();
                    logger.info("GraphQL Response: {}", responseContent);
                });
    }
}
  1. 注册拦截器:
@Bean
public WebGraphQlInterceptor graphQlResponseLoggingInterceptor() {
    return new GraphQlResponseLoggingInterceptor();
}

这种方式可以更精准地控制GraphQL请求的日志记录,无需依赖Logback Access的TeeFilter。


内容的提问来源于stack exchange,提问作者Nodirbek Shamsiev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 18:05:22