如何在Nest.js多租户应用中配置全局路径参数:tenantID?
NestJS 实现全局租户ID路由前缀方案
方法一:全局路由前缀统一配置
直接在应用启动时设置全局路由前缀为:tenantID,所有模块的路由会自动继承这个前缀,无需逐个模块修改。
// main.ts import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); // 设置全局路由前缀为租户ID参数 app.setGlobalPrefix(':tenantID'); await app.listen(3000); } bootstrap();
控制器只需定义自身模块的路由部分:
// users.controller.ts import { Controller, Get, Param } from '@nestjs/common'; @Controller('users') export class UsersController { @Get() getUsers(@Param('tenantID') tenantID: string) { // 直接获取路径中的租户ID,后续可用于数据隔离查询 return `租户 ${tenantID} 的用户列表`; } }
此时访问路径为http://localhost:3000/your-tenant-id/users,完全符合需求。
方法二:模块级路由前缀配置(按需使用)
如果不需要全局统一前缀,可为每个模块单独配置带租户ID的路由前缀:
// users.controller.ts import { Controller, Get, Param } from '@nestjs/common'; // 直接在控制器上指定带租户ID的完整前缀 @Controller(':tenantID/users') export class UsersController { @Get() getUsers(@Param('tenantID') tenantID: string) { return `租户 ${tenantID} 的用户列表`; } }
或者在模块导入时动态配置(需模块支持路由前缀注入):
// app.module.ts import { Module } from '@nestjs/common'; import { UsersModule } from './users/users.module'; import { ConversationsModule } from './conversations/conversations.module'; @Module({ imports: [ // 假设模块支持通过forRoot传入路由前缀 UsersModule.forRoot({ routePrefix: ':tenantID/users' }), ConversationsModule.forRoot({ routePrefix: ':tenantID/conversations' }), ], }) export class AppModule {}
方法三:全局中间件处理租户ID验证与传递
为确保租户ID合法性,可添加全局中间件统一处理:
// tenant.middleware.ts import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; @Injectable() export class TenantMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { const tenantID = req.params.tenantID; // 验证租户ID是否合法(示例:非空检查) if (!tenantID) { return res.status(400).json({ message: '租户ID不能为空' }); } // 将租户ID挂载到请求对象,供后续控制器/服务使用 (req as any).tenantID = tenantID; next(); } }
在main.ts中注册全局中间件:
// main.ts async function bootstrap() { const app = await NestFactory.create(AppModule); app.setGlobalPrefix(':tenantID'); // 注册租户中间件 app.use(TenantMiddleware); await app.listen(3000); } bootstrap();
后续在服务中可直接获取租户ID:
// users.service.ts import { Injectable, Request } from '@nestjs/common'; @Injectable() export class UsersService { getUsers(@Request() req: Request) { const tenantID = (req as any).tenantID; // 基于租户ID查询数据(单库多租户的核心:数据隔离) return this.userRepository.find({ where: { tenantID } }); } }
Swagger 文档适配
若使用Swagger,需添加全局参数说明:
// main.ts import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.setGlobalPrefix(':tenantID'); const config = new DocumentBuilder() .setTitle('多租户API') .setDescription('单库单应用多租户REST API') .setVersion('1.0') .addParameter('tenantID', { in: 'path', required: true, description: '租户唯一标识', schema: { type: 'string' }, }) .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document); await app.listen(3000); } bootstrap();
内容的提问来源于stack exchange,提问作者BratZdenko
相关产品推荐
相关产品推荐

