乐闻世界logo
搜索文章和话题

NestJS 控制器和路由如何工作?

2月17日 22:32

控制器(Controller)的概念

控制器是 NestJS 中负责处理传入请求并返回响应的类。它们使用装饰器来关联路由、HTTP 方法、请求体等,是应用程序的入口点。

控制器的基本结构

typescript
import { 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()

typescript
import { 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'; } }

控制器的作用域

控制器默认使用单例模式,但可以通过装饰器配置作用域:

typescript
import { Scope } from '@nestjs/common'; @Controller({ path: 'users', scope: Scope.REQUEST }) export class UsersController {}

最佳实践

  1. 保持控制器简洁:控制器只负责处理请求和响应,业务逻辑应该在服务中
  2. 使用 DTO 验证:使用数据传输对象(DTO)来验证和转换请求数据
  3. 遵循 RESTful 规范:使用正确的 HTTP 方法和状态码
  4. 使用类验证器:结合 class-validatorclass-transformer 进行数据验证
  5. 避免直接使用 Express 对象:优先使用 NestJS 装饰器而非直接操作 Request/Response 对象
  6. 合理组织路由:使用有意义的路由前缀和参数名
  7. 错误处理:使用异常过滤器统一处理错误

总结

NestJS 控制器和路由系统提供了:

  • 声明式的路由定义
  • 丰富的装饰器支持
  • 灵活的参数获取方式
  • 完整的 HTTP 方法支持
  • 清晰的代码组织结构

掌握控制器和路由是构建 NestJS 应用程序的基础,它们使开发者能够快速定义 API 端点并处理各种 HTTP 请求。

标签:NestJS