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

如何通过自定义注解向NestJS执行上下文添加指定值

需求可实现,通过「自定义装饰器+反射+拦截器」组合即可完成你要的效果

你之前遇到的两个问题本质是对Nest的运行机制理解有偏差:

  • 装饰器属于静态元编程能力,仅在类/方法加载阶段执行,此时请求还未发起,自然拿不到运行时才生成的ExecutionContext
  • 拦截器要接收自定义参数,需要通过装饰器先把参数存入路由元数据,再在拦截器中通过反射读取即可

步骤1:实现自定义装饰器

使用Nest内置的SetMetadata工具方法,把你要传递的自定义值存入路由方法的元数据中:

import { SetMetadata } from '@nestjs/common';

// 定义元数据的key,避免硬编码冲突
export const MY_CUSTOM_CONTEXT_KEY = 'my_custom_context_key';
// 导出你要的@MyAnnotation装饰器
export const MyAnnotation = (customValue: string) => SetMetadata(MY_CUSTOM_CONTEXT_KEY, customValue);

步骤2:实现拦截器读取元数据并写入上下文

在拦截器中注入Reflector工具,读取刚才存入的元数据,再写入当前请求的上下文即可:

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { MY_CUSTOM_CONTEXT_KEY } from './my-annotation.decorator';

@Injectable()
export class CustomContextInterceptor implements NestInterceptor {
  constructor(private reflector: Reflector) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    // 读取当前路由方法上的自定义元数据
    const customValue = this.reflector.get<string>(
      MY_CUSTOM_CONTEXT_KEY,
      context.getHandler()
    );

    // 只有加了@MyAnnotation装饰器的方法才会进入逻辑
    if (customValue) {
      // 以HTTP上下文为例,拿到request对象,把自定义值挂载上去
      // 如果是RPC/WebSocket上下文,调用对应context.switchToXxx()方法即可
      const request = context.switchToHttp().getRequest();
      // 写入自定义值到请求上下文,后续守卫、管道、控制器方法都可以读取该值
      request.myCustomContextValue = customValue;
    }

    return next.handle();
  }
}

步骤3:注册拦截器并使用

首先注册拦截器,推荐全局注册,不用每个控制器单独加:

// 在根模块的providers中添加如下配置
import { APP_INTERCEPTOR } from '@nestjs/core';
import { CustomContextInterceptor } from './custom-context.interceptor';

@Module({
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: CustomContextInterceptor,
    },
  ],
})
export class AppModule {}

之后就可以直接在控制器方法上按你想要的方式使用了:

@Controller('docs')
export class MyController {
  constructor(private readonly service: SubjectsService) {}
  
  @Get('/:Id')
  @MyAnnotation('addThisStringToContext')
  async find(@Param() id: string, @Req() request: Request) {
    // 直接从请求上下文拿到你写入的自定义值
    console.log(request.myCustomContextValue); // 输出:addThisStringToContext
    return await this.service.find(id);
  }
}

内容的提问来源于stack exchange,提问作者Alon Mota

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 00:27:04