如何将NestJS全局前缀中的:companyName参数转为全局变量?
解决NestJS全局前缀中
:companyName参数的全局获取问题 首先明确:绝对不要用全局变量存储请求级别的参数。Node.js是单线程事件循环模型,所有请求共享同一块内存空间,全局变量会被并发请求直接覆盖,导致数据完全错乱。
下面给几个安全可行的方案:
1. 自定义装饰器(最便捷)
直接封装一个装饰器,在控制器、守卫、拦截器里随时获取:companyName参数:
// src/common/decorators/company-name.decorator.ts import { createParamDecorator, ExecutionContext } from '@nestjs/common'; export const CompanyName = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); // 全局前缀的参数会被解析到request.params里 return request.params.companyName; }, );
然后在控制器里直接用:
@Get('users') getUsers(@CompanyName() companyName: string) { console.log('当前企业:', companyName); // 业务逻辑... }
2. 中间件挂载到Request对象
如果需要在全局中间件、守卫等地方统一处理,可把参数挂载到请求对象上——每个请求的req都是独立实例,不会互相干扰:
// src/common/middlewares/company.middleware.ts import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; @Injectable() export class CompanyMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { // 从params里取出全局前缀的companyName req['companyName'] = req.params.companyName; next(); } }
然后在main.ts或模块里注册全局中间件:
// main.ts app.use(new CompanyMiddleware());
之后在控制器或其他地方通过req.companyName获取:
@Get('orders') getOrders(@Req() req: Request) { console.log('企业名称:', req['companyName']); }
3. 请求作用域的提供者(全局共享服务)
如果需要在多个服务里共享这个参数,可以创建一个请求作用域的服务——每个请求会生成独立的服务实例,完全避免并发冲突:
// src/common/services/company-context.service.ts import { Injectable, Scope } from '@nestjs/common'; @Injectable({ scope: Scope.REQUEST }) export class CompanyContextService { private companyName: string; setCompanyName(name: string) { this.companyName = name; } getCompanyName() { return this.companyName; } }
然后在中间件里注入这个服务并设置参数:
// 修改CompanyMiddleware import { CompanyContextService } from '../services/company-context.service'; @Injectable() export class CompanyMiddleware implements NestMiddleware { constructor(private readonly companyContext: CompanyContextService) {} use(req: Request, res: Response, next: NextFunction) { this.companyContext.setCompanyName(req.params.companyName); next(); } }
最后在任意服务或控制器里注入CompanyContextService,调用getCompanyName()就能拿到当前请求的企业名称:
@Injectable() export class UserService { constructor(private readonly companyContext: CompanyContextService) {} getUsers() { const companyName = this.companyContext.getCompanyName(); // 基于企业名称查询数据... } }
内容的提问来源于stack exchange,提问作者Thomas Kottas
相关产品推荐
相关产品推荐

