Skip to content

NestJS 核心概念

概览

NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架。它使用渐进式 JavaScript,完全支持 TypeScript,并结合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数响应式编程)的元素。

架构特点

  • 基于 Express 或 Fastify
  • 模块化架构设计
  • 依赖注入系统
  • 装饰器驱动开发
  • TypeScript 原生支持

核心概念

模块 (Modules)

模块是 NestJS 应用程序的基本构建块,用于组织应用程序结构。

关键特性:

  • 使用 @Module() 装饰器定义
  • 封装相关的控制器和服务
  • 支持模块间的导入导出
  • 实现代码的模块化和可重用性

基本结构:

typescript
@Module({
  imports: [],      // 导入其他模块
  controllers: [],  // 注册控制器
  providers: [],    // 注册服务提供者
  exports: []       // 导出供其他模块使用
})
export class AppModule {}

模块类型:

  • 功能模块:封装特定业务功能
  • 共享模块:可被多个模块导入
  • 全局模块:使用 @Global() 装饰器
  • 动态模块:运行时配置

控制器 (Controllers)

控制器负责处理传入的请求并返回响应给客户端。

关键特性:

  • 使用 @Controller() 装饰器定义
  • 处理 HTTP 请求路由
  • 绑定请求方法(GET、POST、PUT、DELETE 等)
  • 参数提取和验证

基本示例:

typescript
@Controller('users')
export class UsersController {
  @Get()
  findAll() {
    return 'This returns all users';
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return `This returns user #${id}`;
  }

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return 'This creates a new user';
  }
}

常用装饰器:

  • @Get(), @Post(), @Put(), @Delete(), @Patch()
  • @Param(), @Query(), @Body(), @Headers()
  • @Req(), @Res()

服务 (Providers/Services)

服务是可注入的类,用于处理业务逻辑和数据访问。

关键特性:

  • 使用 @Injectable() 装饰器
  • 通过依赖注入使用
  • 封装业务逻辑
  • 可被控制器或其他服务注入

基本示例:

typescript
@Injectable()
export class UsersService {
  private users = [];

  findAll() {
    return this.users;
  }

  findOne(id: number) {
    return this.users.find(user => user.id === id);
  }

  create(user: any) {
    this.users.push(user);
    return user;
  }
}

依赖注入:

typescript
@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}
}

中间件 (Middleware)

中间件是在路由处理程序之前调用的函数,可以访问请求和响应对象。

关键特性:

  • 执行任何代码
  • 修改请求和响应对象
  • 结束请求-响应循环
  • 调用下一个中间件

实现方式:

1. 函数式中间件:

typescript
export function logger(req: Request, res: Response, next: NextFunction) {
  console.log(`Request...`);
  next();
}

2. 类中间件:

typescript
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log('Request...');
    next();
  }
}

应用中间件:

typescript
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('users');
  }
}

守卫 (Guards)

守卫用于确定请求是否应该被路由处理程序处理,主要用于授权。

关键特性:

  • 使用 @Injectable()CanActivate 接口
  • 在中间件之后、拦截器之前执行
  • 返回 boolean 或 Promise<boolean>
  • 适用于身份验证和授权

基本示例:

typescript
@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    return this.validateRequest(request);
  }
}

使用方式:

typescript
@Controller('users')
@UseGuards(AuthGuard)
export class UsersController {}

应用级别:

  • 全局守卫
  • 控制器级守卫
  • 路由级守卫

拦截器 (Interceptors)

拦截器可以在方法执行前后添加额外的逻辑,类似于面向切面编程(AOP)。

关键特性:

  • 使用 @Injectable()NestInterceptor 接口
  • 在方法执行前后绑定额外逻辑
  • 转换函数返回的结果
  • 扩展基本函数行为

基本示例:

typescript
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('Before...');
    const now = Date.now();
    
    return next.handle().pipe(
      tap(() => console.log(`After... ${Date.now() - now}ms`))
    );
  }
}

使用场景:

  • 日志记录
  • 响应数据转换
  • 缓存管理
  • 超时处理
  • 异常映射

过滤器 (Exception Filters)

异常过滤器用于捕获和处理应用程序中抛出的异常。

关键特性:

  • 使用 @Catch() 装饰器
  • 实现 ExceptionFilter 接口
  • 统一异常处理
  • 自定义错误响应格式

基本示例:

typescript
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message: exception.message,
    });
  }
}

使用方式:

typescript
@Post()
@UseFilters(HttpExceptionFilter)
create(@Body() createUserDto: CreateUserDto) {}

其他核心概念

管道 (Pipes)

管道用于数据转换和验证。

功能:

  • 数据转换:将输入数据转换为所需格式
  • 数据验证:验证输入数据,无效时抛出异常

内置管道:

  • ValidationPipe
  • ParseIntPipe
  • ParseBoolPipe
  • ParseArrayPipe
  • ParseUUIDPipe

示例:

typescript
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
  return this.usersService.findOne(id);
}

装饰器 (Decorators)

NestJS 广泛使用装饰器来定义应用程序的结构和行为。

常用装饰器类别:

  • 类装饰器:@Module(), @Controller(), @Injectable()
  • 方法装饰器:@Get(), @Post(), @UseGuards()
  • 参数装饰器:@Param(), @Body(), @Query()
  • 属性装饰器:@Inject()

依赖注入 (Dependency Injection)

NestJS 内置强大的依赖注入系统。

Provider 作用域:

  • DEFAULT:单例模式(默认)
  • REQUEST:每个请求创建新实例
  • TRANSIENT:每次注入创建新实例

自定义 Provider:

typescript
{
  provide: 'CONFIG',
  useValue: { apiKey: 'xxx' }
}

请求生命周期

  1. 接收请求
  2. 中间件执行
  3. 守卫执行
  4. 拦截器(请求前)
  5. 管道执行
  6. 路由处理器执行
  7. 拦截器(响应后)
  8. 异常过滤器(如有异常)
  9. 返回响应

最佳实践

  1. 模块化设计:按功能划分模块
  2. 单一职责:每个类只负责一个功能
  3. 依赖注入:充分利用 DI 系统
  4. 类型安全:使用 TypeScript 和 DTO
  5. 异常处理:统一使用异常过滤器
  6. 验证管道:使用 ValidationPipe 和 class-validator
  7. 配置管理:使用 ConfigModule
  8. 日志记录:使用内置 Logger 或集成第三方库

学习路径建议

  1. 从简单的控制器和服务开始
  2. 理解模块化架构
  3. 掌握依赖注入机制
  4. 学习请求生命周期和各组件的执行顺序
  5. 实践中间件、守卫、拦截器的使用场景
  6. 深入学习高级特性(微服务、WebSocket、GraphQL 等)

相关资源

Released under the MIT License.