模块与控制器基础:@Module 装饰器详解、控制器创建、路由与 HTTP 方法映射

在 NestJS 中,模块(Module)是组织代码的基本单元,而控制器(Controller)负责处理传入的 HTTP 请求并返回响应。本章将深入解析 @Module() 装饰器的核心配置,演示如何创建控制器,并建立路由与 HTTP 方法之间的映射关系。

1. @Module 装饰器详解

@Module() 装饰器将一个类标记为 NestJS 模块,它是应用架构的“骨架”。每个模块通过元数据对象声明其内部的组件、对外暴露的服务以及依赖的其他模块。

属性 类型 说明
controllers Array<Type<any>> 该模块下需要实例化的控制器集合,负责处理路由
providers Array<Type<any>> 该模块中可被注入的服务、仓库、工厂等提供者
imports Array<Type<any>> 导入其他模块,以使用其导出的提供者
exports Array<Type<any>> 将本模块的部分提供者暴露给导入本模块的其他模块
关键原则:模块是单例作用域。默认情况下,提供者在模块内是单例的,且模块本身也是单例的——无论被导入多少次,Nest 只会创建一个实例。
// app.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users/users.controller';
import { UsersService } from './users/users.service';

@Module({
  controllers: [UsersController],
  providers: [UsersService],
})
export class AppModule {}

2. 控制器(Controller)创建

控制器使用 @Controller() 装饰器定义,其核心职责是:

  • 接收特定路径的 HTTP 请求
  • 调用业务逻辑(通常委托给服务层)
  • 返回响应给客户端

@Controller() 可以接收一个可选参数——路由前缀。前缀有助于对相关端点进行分组,避免路由冲突。

// users.controller.ts
import { Controller, Get } from '@nestjs/common';

@Controller('users')  // 路由前缀:/users
export class UsersController {
  @Get()
  findAll(): string {
    return '返回所有用户';
  }
}
最佳实践:始终为控制器设置有意义的路由前缀(如 users、orders),这不仅能提升代码可读性,还能在全局前缀或版本控制时保持灵活性。

3. 路由与 HTTP 方法映射

NestJS 为每个标准 HTTP 方法提供了对应的装饰器:@Get()、@Post()、@Put()、@Delete()、@Patch() 等。这些装饰器可以接收一个路径参数,用于定义子路由。

装饰器 HTTP 方法 典型用途
@Get() GET 查询资源列表或单个资源
@Post() POST 创建新资源
@Put() PUT 全量更新资源
@Delete() DELETE 删除资源
@Patch() PATCH 部分更新资源
// users.controller.ts
import { Controller, Get, Post, Param, Body } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get()
  findAll(): string {
    return '获取所有用户';
  }

  @Get(':id')
  findOne(@Param('id') id: string): string {
    return `获取用户 ${id}`;
  }

  @Post()
  create(@Body() createUserDto: any): string {
    return `创建用户:${JSON.stringify(createUserDto)}`;
  }
}
路由冲突注意:当存在静态路由(如 @Get('profile'))和动态路由(如 @Get(':id'))时,静态路由必须声明在动态路由之前,否则 Nest 会将 profile 匹配为 :id 参数。

4. 模块与控制器协作流程

下图展示了 NestJS 启动时,模块如何加载控制器,以及请求如何通过路由映射到达控制器方法:

模块与控制器协作流程 AppModule @Module({...}) UsersController @Controller('users') 路由映射表 GET /users → findAll() 注册 解析 HTTP 请求 GET /users 路由匹配 查找对应处理器 响应返回 200 OK / 数据 进入 执行 说明: 模块注册控制器 → 控制器解析装饰器生成路由映射表 → 请求到达时按路径和方法匹配到对应方法 → 执行后返回响应。

5. 完整示例:用户模块

以下是一个包含模块、控制器和基本路由映射的完整示例:

// users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';

@Module({
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

// users.controller.ts
import { Controller, Get, Post, Put, Delete, Param, Body } from '@nestjs/common';

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

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }

  @Post()
  create(@Body() createUserDto: any) {
    return this.usersService.create(createUserDto);
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() updateUserDto: any) {
    return this.usersService.update(+id, updateUserDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.usersService.remove(+id);
  }
}
路由映射总结:
  • GET /users → findAll()
  • GET /users/:id → findOne()
  • POST /users → create()
  • PUT /users/:id → update()
  • DELETE /users/:id → remove()
每个控制器方法通过装饰器明确声明其处理的 HTTP 方法和路径,NestJS 在启动时自动构建完整的路由映射表。