控制器(Controller)的概念
控制器是 NestJS 中负责处理传入请求并返回响应的类。它们使用装饰器来关联路由、HTTP 方法、请求体等,是应用程序的入口点。
控制器的基本结构
typescriptimport { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common'; import { UsersService } from './users.service'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; @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: CreateUserDto) { return this.usersService.create(createUserDto); } @Put(':id') update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) { return this.usersService.update(id, updateUserDto); } @Delete(':id') remove(@Param('id') id: string) { return this.usersService.remove(id); } }
路由装饰器
@Controller()
@Controller() 装饰器用于定义控制器类,可以指定路由前缀:
typescript@Controller('users') export class UsersController {}
HTTP 方法装饰器
NestJS 提供了所有标准 HTTP 方法的装饰器:
@Get()- GET 请求@Post()- POST 请求@Put()- PUT 请求@Patch()- PATCH 请求@Delete()- DELETE 请求@Options()- OPTIONS 请求@Head()- HEAD 请求@All()- 所有 HTTP 方法
typescript@Get() findAll() { return this.usersService.findAll(); } @Post() create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); }
路由参数
路径参数
使用 @Param() 装饰器获取路径参数:
typescript@Get(':id') findOne(@Param('id') id: string) { return this.usersService.findOne(id); } // 或者使用对象解构 @Get(':id') findOne(@Param() params: { id: string }) { return this.usersService.findOne(params.id); }
查询参数
使用 @Query() 装饰器获取查询参数:
typescript@Get() findAll(@Query('page') page: number, @Query('limit') limit: number) { return this.usersService.findAll(page, limit); } // 或者获取所有查询参数 @Get() findAll(@Query() query: { page: number; limit: number }) { return this.usersService.findAll(query.page, query.limit); }
请求体
使用 @Body() 装饰器获取请求体:
typescript@Post() create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); } // 或者获取特定字段 @Post() create(@Body('name') name: string, @Body('email') email: string) { return this.usersService.create({ name, email }); }
请求头
使用 @Headers() 装饰器获取请求头:
typescript@Get() findAll(@Headers('authorization') authorization: string) { return this.usersService.findAll(authorization); } // 或者获取所有请求头 @Get() findAll(@Headers() headers: Record<string, string>) { return this.usersService.findAll(headers); }
请求对象和响应对象
使用 @Req() 和 @Res()
typescriptimport { Req, Res } from '@nestjs/common'; import { Request, Response } from 'express'; @Get() findAll(@Req() req: Request, @Res() res: Response) { const data = this.usersService.findAll(); return res.json(data); }
注意:使用 @Res() 时,必须显式调用响应方法(如 res.json()),否则会导致请求挂起。
状态码
使用 @HttpCode() 装饰器设置状态码:
typescript@Post() @HttpCode(201) create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); }
响应头
使用 @Header() 装饰器设置响应头:
typescript@Get() @Header('Cache-Control', 'no-cache') findAll() { return this.usersService.findAll(); }
重定向
使用 @Redirect() 装饰器或 redirect() 方法:
typescript@Get() @Redirect('https://nestjs.com', 301) findAll() { return this.usersService.findAll(); } // 或者动态重定向 @Get('docs') @Redirect() getDocs(@Query('version') version) { if (version && version === '5') { return { url: 'https://docs.nestjs.com/v5/', statusCode: 301 }; } }
路由通配符
NestJS 支持路由通配符模式:
typescript@Get('ab*cd') findAll() { // 匹配 abcd, abxcd, abRANDOMcd, ab123cd 等 }
子域路由
使用 @Controller() 装饰器的 host 选项:
typescript@Controller({ host: 'admin.example.com' }) export class AdminController { @Get() index() { return 'Admin page'; } }
控制器的作用域
控制器默认使用单例模式,但可以通过装饰器配置作用域:
typescriptimport { Scope } from '@nestjs/common'; @Controller({ path: 'users', scope: Scope.REQUEST }) export class UsersController {}
最佳实践
- 保持控制器简洁:控制器只负责处理请求和响应,业务逻辑应该在服务中
- 使用 DTO 验证:使用数据传输对象(DTO)来验证和转换请求数据
- 遵循 RESTful 规范:使用正确的 HTTP 方法和状态码
- 使用类验证器:结合
class-validator和class-transformer进行数据验证 - 避免直接使用 Express 对象:优先使用 NestJS 装饰器而非直接操作 Request/Response 对象
- 合理组织路由:使用有意义的路由前缀和参数名
- 错误处理:使用异常过滤器统一处理错误
总结
NestJS 控制器和路由系统提供了:
- 声明式的路由定义
- 丰富的装饰器支持
- 灵活的参数获取方式
- 完整的 HTTP 方法支持
- 清晰的代码组织结构
掌握控制器和路由是构建 NestJS 应用程序的基础,它们使开发者能够快速定义 API 端点并处理各种 HTTP 请求。