如何在Spring for GraphQL的WebGraphQlInterceptor中获取HttpServletRequest
从GraphQL Kickstarter迁移到Spring for GraphQL:自定义GraphQLContext获取HttpServletRequest全量信息
核心思路
Spring for GraphQL中,WebGraphQlRequest可以通过ServerWebExchange拿到原生的HttpServletRequest,进而提取请求头、参数、自定义属性,再将这些信息注入到GraphQLContext中供后续Resolver使用。
步骤1:自定义GraphQLContext(可选,推荐)
创建自定义上下文类封装需要的请求信息,方便后续业务代码直接调用:
import graphql.GraphQLContext; import jakarta.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; public class CustomGraphQLContext implements GraphQLContext { private final Map<String, String> headers; private final Map<String, String> requestParams; private final Map<String, Object> attributes; public CustomGraphQLContext(HttpServletRequest request) { // 提取请求头 this.headers = request.getHeaderNames() .asIterator() .collect(Collectors.toMap( headerName -> headerName, request::getHeader )); // 提取请求参数(单值处理,多值可调整为List<String>) this.requestParams = request.getParameterMap() .entrySet() .stream() .collect(Collectors.toMap( Map.Entry::getKey, entry -> entry.getValue()[0] )); // 提取请求属性 this.attributes = new HashMap<>(); request.getAttributeNames().asIterator() .forEach(attrName -> attributes.put(attrName, request.getAttribute(attrName))); } // 业务快捷方法 public String getDebugParam() { return requestParams.get("debug"); } public String getUsername() { return (String) attributes.get("security.web.username"); } // 实现GraphQLContext基础方法(如需直接操作上下文Map) @Override public <T> T get(Object key) { if (headers.containsKey(key)) return (T) headers.get(key); if (requestParams.containsKey(key)) return (T) requestParams.get(key); return (T) attributes.get(key); } }
步骤2:实现WebGraphQlInterceptor注入上下文
通过拦截器获取HttpServletRequest并初始化自定义上下文,绑定到GraphQL执行上下文:
import org.springframework.graphql.server.WebGraphQlInterceptor; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; import reactor.core.publisher.Mono; public class CustomContextInterceptor implements WebGraphQlInterceptor { @Override public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) { return request.getExchange() // 获取原生HttpServletRequest .map(exchange -> exchange.getNativeRequest(HttpServletRequest.class)) // 初始化自定义上下文 .map(CustomGraphQLContext::new) // 将上下文绑定到执行输入 .doOnNext(context -> request.configureExecutionInput((input, builder) -> builder.graphQLContext(context).build() )) // 继续执行请求链 .then(chain.next(request)); } }
步骤3:注册拦截器到Spring容器
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.graphql.server.WebGraphQlInterceptor; @Configuration public class GraphQLConfig { @Bean public WebGraphQlInterceptor customContextInterceptor() { return new CustomContextInterceptor(); } }
步骤4:在Resolver中使用自定义上下文
方式1:通过DataFetchingEnvironment获取
import graphql.schema.DataFetchingEnvironment; import org.springframework.graphql.data.method.annotation.QueryMapping; import org.springframework.stereotype.Controller; @Controller public class DemoResolver { @QueryMapping public String hello(DataFetchingEnvironment env) { CustomGraphQLContext context = env.getContext(); String debugMode = context.getDebugParam(); String username = context.getUsername(); return String.format("Hello %s, debug mode: %s", username, debugMode); } }
方式2:直接注入上下文(Spring注解支持)
import org.springframework.graphql.data.method.annotation.GraphQLContext; import org.springframework.graphql.data.method.annotation.QueryMapping; import org.springframework.stereotype.Controller; @Controller public class DemoResolver { @QueryMapping public String hello(@GraphQLContext CustomGraphQLContext context) { return String.format("Hello %s, debug mode: %s", context.getUsername(), context.getDebugParam()); } }
替代方案:使用默认上下文(无需自定义类)
如果不需要封装快捷方法,也可以直接用DefaultGraphQLContext存入键值对:
@Override public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) { return request.getExchange() .map(exchange -> exchange.getNativeRequest(HttpServletRequest.class)) .doOnNext(servletRequest -> { DefaultGraphQLContext context = new DefaultGraphQLContext(); // 存入请求头 servletRequest.getHeaderNames().asIterator() .forEach(header -> context.put(header, servletRequest.getHeader(header))); // 存入请求参数 servletRequest.getParameterMap().forEach((key, values) -> context.put(key, values[0])); // 存入自定义属性 context.put("username", servletRequest.getAttribute("security.web.username")); request.configureExecutionInput((input, builder) -> builder.graphQLContext(context).build() ); }) .then(chain.next(request)); }
此时Resolver中通过env.getContext().get("username")即可获取对应值。
内容的提问来源于stack exchange,提问作者Mohamed Ayman Naguib
相关产品推荐
相关产品推荐

