NestJS如何向CacheKey装饰器传递动态请求参数?
动态生成NestJS缓存键的实现方案
默认的@CacheKey装饰器无法直接传入运行时的请求参数——因为装饰器是在类初始化阶段执行的,拿不到请求上下文。不过有两种可靠的方式实现你要的动态缓存键逻辑:
方案一:自定义CacheInterceptor(兼容所有NestJS版本)
继承默认的CacheInterceptor,重写trackBy方法来生成符合要求的缓存键:
// custom-cache.interceptor.ts import { CacheInterceptor, ExecutionContext } from '@nestjs/common'; export class CustomCacheInterceptor extends CacheInterceptor { trackBy(context: ExecutionContext): string | undefined { const request = context.switchToHttp().getRequest(); // 根据实际需求获取请求参数,比如URL参数、Query、Body等 const userId = request.query.userId; // 拼接成「模块名-方法名-请求参数」格式的缓存键 return `userModule_getUserById_${userId}`; } }
然后在控制器中替换默认拦截器:
import { CacheTTL, Controller, Get, Req, UseInterceptors, } from '@nestjs/common'; import { AppService } from './app.service'; import { CustomCacheInterceptor } from './custom-cache.interceptor'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @UseInterceptors(CustomCacheInterceptor) @CacheTTL(3600) @Get() async getHello(@Req() req: Request): Promise<string> { return new Promise((resolve) => { setTimeout(() => { resolve('Hello World!'); }, 3000); }); } }
方案二:使用CacheKey工厂函数(NestJS 9+支持)
如果你的NestJS版本在9及以上,@CacheKey支持传入工厂函数,直接通过上下文获取请求参数:
import { CacheInterceptor, CacheKey, CacheTTL, Controller, Get, Req, UseInterceptors, ExecutionContext, } from '@nestjs/common'; import { AppService } from './app.service'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @UseInterceptors(CacheInterceptor) @CacheTTL(3600) @CacheKey((context: ExecutionContext) => { const request = context.switchToHttp().getRequest(); const userId = request.query.userId; return `userModule_getUserById_${userId}`; }) @Get() async getHello(@Req() req: Request): Promise<string> { return new Promise((resolve) => { setTimeout(() => { resolve('Hello World!'); }, 3000); }); } }
缓存清理实现
后续要按模块名、方法名或用户ID清理缓存,可通过CacheManager操作:
import { Inject, CACHE_MANAGER } from '@nestjs/common'; import { Cache } from 'cache-manager'; // 在服务/控制器中注入缓存管理器 constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {} // 清理指定用户的缓存 async clearUserCache(userId: string) { const targetKey = `userModule_getUserById_${userId}`; await this.cacheManager.del(targetKey); } // 批量清理整个userModule的缓存(需缓存存储支持keys查询,如Redis) async clearUserModuleCache() { const moduleKeys = await this.cacheManager.store.keys('userModule_*'); await Promise.all(moduleKeys.map(key => this.cacheManager.del(key))); }
内容的提问来源于stack exchange,提问作者Yasin Bikmazer
相关产品推荐
相关产品推荐

