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
相关产品推荐
相关产品推荐

