内容提要
本文介绍 NestJS 进阶用法,包括:Logger 日志系统支持自定义与依赖注入;ModuleRef 用于检索和动态实例化提供者;生命周期钩子管理应用启动与关闭;Swagger 生成接口文档,CLI 插件自动注解 DTO;JWT 实现身份验证与守卫鉴权;ConfigModule 统一管理环境变量配置并支持验证。
延伸解读
日志系统:从内置到自定义的平滑扩展
NestJS 内置 Logger 基于文本输出,支持通过 NestApplicationOptions.logger 配置日志等级或禁用。若需替换,实现 LoggerService 接口即可完全覆盖;若仅扩展,继承 ConsoleLogger 并重写方法更轻量。手动实例化 Logger 会破坏单例,推荐包装 LoggerModule 并通过依赖注入统一管理,再结合 app.useLogger() 和 bufferLogs 应用于系统日志。
ModuleRef:灵活检索与动态实例化的边界
ModuleRef 允许绕过模块依赖关系,直接从全局上下文检索提供者实例,但需注意 strict 选项。get() 不能用于作用域提供者,需改用 resolve() 并配合 ContextIdFactory 管理实例唯一性。对于请求作用域提供者,必须通过 registerRequestByContextId() 或 getByRequest() 注册请求对象,否则 REQUEST 注入为 undefined。create() 可动态实例化未注册的类,但依赖必须在该模块内可访问。
生命周期钩子:启动与关闭的精细控制
Nest 提供 onModuleInit、onApplicationBootstrap、onModuleDestroy、beforeApplicationShutdown 和 onApplicationShutdown 等钩子,用于在应用启动和关闭阶段执行自定义逻辑。异步钩子可推迟初始化,适合数据库连接等操作。注意请求作用域类没有生命周期钩子。关闭钩子默认不监听系统信号,需显式调用 app.enableShutdownHooks(),且在 Windows 上可能表现不稳定。
Swagger 与 CLI 插件:提升文档效率与可维护性
Swagger 通过 SwaggerModule 和 DocumentBuilder 生成符合 OpenAPI 规范的接口文档,并支持丰富的 @Api*() 装饰器描述接口。手动为每个 DTO 属性添加 @ApiProperty() 繁琐且与 class-validator 重复,启用 CLI 插件可自动注解 DTO,并根据注释生成描述和示例。需注意 DTO 文件名后缀、更新插件后删除 dist 重新构建,以及使用 @nestjs/swagger 的映射类型工具以确保插件获取模式信息。
Q&A
NestJS 中如何配置 Logger 来禁用日志或设置最低日志等级?
在创建 Nest 应用时,通过 NestApplicationOptions.logger 配置。设置为 false 可禁用日志;也可以传入日志等级数组,如 ['log'],则 log 及以上等级(warn、error 等)的日志会被输出。
ModuleRef 的 get() 和 resolve() 方法有什么区别?
get() 用于检索当前模块中已实例化的提供者、控制器或可注入项,若提供者来自其他模块需设置 strict: false 从全局上下文检索;resolve() 用于解析作用域提供者(瞬态或请求作用域),返回 Promise,多次调用返回不同实例,可通过 ContextIdFactory 创建相同上下文标识来获取相同实例。
NestJS 的生命周期钩子有哪些?分别在什么时机调用?
NestJS 提供以下钩子:onModuleInit() 在模块依赖解析完成后调用;onApplicationBootstrap() 在所有模块初始化后、监听连接前调用;onModuleDestroy() 在收到终止信号或 app.close() 后调用;beforeApplicationShutdown() 在所有 onModuleDestroy 完成后调用;onApplicationShutdown() 在连接关闭后调用。注意请求作用域的类没有生命周期钩子。
如何在 NestJS 中集成 Swagger 生成接口文档?
安装 @nestjs/swagger,在 main.ts 中使用 SwaggerModule 和 DocumentBuilder:先通过 DocumentBuilder 配置文档(如 setTitle、setDescription、setVersion),然后调用 SwaggerModule.createDocument(app, config) 生成文档对象,最后用 SwaggerModule.setup('api', app, document) 启动 Swagger UI。
NestJS 的 Swagger CLI 插件有什么作用?如何启用?
CLI 插件可自动为 DTO 属性添加 @ApiProperty 注解,根据问号设置 required,根据类型设置 type 或 enum,根据默认值设置 default,根据 class-validator 装饰器设置验证规则,并为端点添加响应装饰器。启用方式:在 nest-cli.json 的 compilerOptions.plugins 中添加 { "name": "@nestjs/swagger", "options": { "classValidatorShim": true, "introspectComments": true } }。
在 NestJS 中如何使用 JWT 实现身份验证?
安装 @nestjs/jwt,在模块中导入 JwtModule.register({ global: true, secret: '密钥', signOptions: { expiresIn: '1d' } })。在服务中注入 JwtService,使用 signAsync() 生成 token(可包含用户名、角色等),使用 verifyAsync() 验证 token。创建 AuthGuard 守卫,从请求头提取 Bearer token,验证后放行。
NestJS 的 ConfigModule 如何管理环境变量?
安装 @nestjs/config,在根模块中导入 ConfigModule.forRoot({ isGlobal: true, envFilePath: '.env', load: [configuration], expandVariables: true, cache: true, validate })。通过 ConfigService 的 get() 方法读取配置值,支持泛型和默认值。可使用 registerAs() 创建命名空间,使用 forFeature() 局部注册配置。