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

Spring Boot 3.1.1 GraphQL应用:请求结束后清空GraphQLContext及缓存方案

Spring Boot 3.1.1 GraphQL 上下文清理与缓存方案

一、请求结束后清空GraphQLContext的实现

先提个醒:你当前代码里在Controller构造方法中初始化的GraphQLContext是单例的(Spring默认Controller是单例),多请求之间会互相污染数据,正确的做法是用请求绑定的GraphQLContext,而非自定义单例实例。

第一步:修正Controller的上下文获取方式

应该从DataFetchingEnvironment中获取当前请求的上下文,而不是自己new:

public class OrderInfoController {

    @QueryMapping
    public String prepareName(@Argument String orderId, DataFetchingEnvironment env) {
        GraphQLContext context = env.getGraphQlContext();
        context.put("name", "Darren");
        return " welcome !";
    }

    @SchemaMapping
    public String getName(@Argument OrderInfo orderInfo, DataFetchingEnvironment env) {
        GraphQLContext context = env.getGraphQlContext();
        String name = context.get("name");
        return "hello " + name;
    }
}

第二步:请求结束后清空上下文的两种方式

方式1:用GraphQL拦截器(GraphQlInterceptor)

实现GraphQlInterceptor,在请求完成后执行清理,不管请求成功还是失败都会触发:

@Component
public class ContextCleanupInterceptor implements GraphQlInterceptor {
    @Override
    public Mono<Object> intercept(GraphQlRequest request, Chain chain) {
        return chain.next(request)
                .doFinally(signalType -> {
                    GraphQLContext context = request.getGraphQlContext();
                    context.clear();
                });
    }
}

方式2:利用Spring HTTP请求生命周期回调

如果你的GraphQL是基于HTTP的,可以用@ControllerAdvice结合@AfterCompletion,在HTTP请求结束后清理:

@ControllerAdvice
public class RequestCleanupAdvice {
    @AfterCompletion
    public void afterRequestCompletion(HttpServletRequest request) {
        GraphQLContext context = (GraphQLContext) request.getAttribute(GraphQlHttpServletRequestHandler.GRAPHQL_CONTEXT_ATTRIBUTE);
        if (context != null) {
            context.clear();
        }
    }
}

二、除GraphQLContext外的其他数据缓存方式

1. 请求级缓存:Request-scoped Bean

定义一个请求作用域的Bean,Spring会在请求结束后自动销毁它,不用手动清理:

@Component
@RequestScope
public class RequestCache {
    private final Map<String, Object> data = new HashMap<>();

    public void put(String key, Object value) {
        data.put(key, value);
    }

    public Object get(String key) {
        return data.get(key);
    }

    public void clear() {
        data.clear();
    }
}

直接在Controller或Service中注入使用就行。

2. 方法级缓存:Spring Cache抽象

用@Cacheable等注解实现方法结果的缓存,适合跨请求的重复数据查询。先启用缓存:

@SpringBootApplication
@EnableCaching
public class GraphqlApplication {
    public static void main(String[] args) {
        SpringApplication.run(GraphqlApplication.class, args);
    }
}

然后在服务层用:

@Service
public class OrderService {
    @Cacheable(value = "orderCache", key = "#orderId")
    public OrderInfo getOrderById(String orderId) {
        // 这里写实际的查询逻辑
        return new OrderInfo();
    }
}

3. 本地内存缓存:Caffeine/Guava Cache

适合存储高频访问的非敏感数据,比如用Caffeine:
先加依赖:

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
</dependency>

配置缓存Bean:

@Configuration
public class CacheConfig {
    @Bean
    public Cache<String, Object> localCache() {
        return Caffeine.newBuilder()
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .maximumSize(1000)
                .build();
    }
}

注入后直接用localCache.put()和localCache.get()操作。

4. 分布式缓存:Redis

如果是分布式应用,用Redis实现跨节点数据共享。先加依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置Redis连接后,用StringRedisTemplate或者结合Spring Cache抽象使用即可。

内容的提问来源于stack exchange,提问作者george jiang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:20:34