从零入门 NestJS:构建你的第一个 REST API(四)创建第一个 Controller

286 阅读3分钟

创建第一个 Controller

在 NestJS 中,Controller(控制器)负责处理客户端的请求和返回响应。每个 Controller 通过装饰器 @Controller 声明路由前缀,内部方法通过 @Get@Post 等装饰器定义具体接口。

Controller 基本概念

  • 职责:接收请求、调用服务层处理业务、返回响应。
  • 装饰器@Controller('路由前缀'),方法上用 @Get()@Post() 等声明 HTTP 路由。

创建 Hello World Controller

// src/app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller() // 根路由
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}
  • 访问 GET / 时,返回 "Hello World!"。
  • AppService 负责业务逻辑,控制器只负责路由和响应。

创建用户注册接口

// src/user/user.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user') // 路由前缀 /user
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post('register')
  register(@Body() body: { username: string; password: string }) {
    return this.userService.register(body);
  }
}
  • 访问 POST /user/register,提交 JSON 数据 { username, password }
  • 通过 @Body() 装饰器获取请求体参数。

路由参数与查询参数

import { Controller, Get, Param, Query } from '@nestjs/common';

@Controller('user')
export class UserController {
  @Get(':id')
  getUser(@Param('id') id: string, @Query('detail') detail: string) {
    return { id, detail };
  }
}
  • 访问 /user/123?detail=full,可获取路径参数和查询参数。

参数解析与管道(Pipe)应用

NestJS 支持通过内置和自定义 Pipe 对参数进行类型转换和校验,常用于 @Param@Query@Body 等装饰器。

1. 路由参数类型转换

import { Controller, Get, Param, ParseIntPipe } from '@nestjs/common';

@Controller('user')
export class UserController {
  @Get(':id')
  getUserById(@Param('id', ParseIntPipe) id: number) {
    // id 已自动转换为 number 类型
    return { id };
  }
}

2. 查询参数校验与转换

import { Controller, Get, Query, DefaultValuePipe, ParseBoolPipe } from '@nestjs/common';

@Controller('user')
export class UserController {
  @Get('list')
  getUserList(
    @Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number,
    @Query('active', new DefaultValuePipe(false), ParseBoolPipe) active: boolean,
  ) {
    return { page, active };
  }
}

3. 请求体参数校验(结合 class-validator)

// dto/create-user.dto.ts
import { IsString, Length } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @Length(3, 20)
  username: string;

  @IsString()
  @Length(6, 20)
  password: string;
}
// user.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';

@Controller('user')
export class UserController {
  @Post('register')
  register(@Body() body: CreateUserDto) {
    // 自动校验 username 和 password
    return { message: '注册成功', user: body };
  }
}

需在 main.ts 中启用全局校验管道:

import { ValidationPipe } from '@nestjs/common';
app.useGlobalPipes(new ValidationPipe());

集成 Swagger 自动生成 API 文档

NestJS 推荐使用 Swagger 自动生成接口文档,方便前后端协作和接口调试。

1. 安装依赖

npm install --save @nestjs/swagger swagger-ui-express

2. 在 main.ts 启用 Swagger

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const config = new DocumentBuilder()
    .setTitle('NestJS 示例 API')
    .setDescription('自动生成的接口文档')
    .setVersion('1.0')
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api-docs', app, document);

  await app.listen(3000);
}
bootstrap();

3. Controller 上添加 Swagger 装饰器

import { Controller, Post, Body } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBody, ApiResponse } from '@nestjs/swagger';
import { CreateUserDto } from './dto/create-user.dto';

@ApiTags('用户')
@Controller('user')
export class UserController {
  @Post('register')
  @ApiOperation({ summary: '用户注册' })
  @ApiBody({ type: CreateUserDto })
  @ApiResponse({ status: 201, description: '注册成功' })
  register(@Body() body: CreateUserDto) {
    return { message: '注册成功', user: body };
  }
}
  • @ApiTags:为 Controller 分组。
  • @ApiOperation:描述接口用途。
  • @ApiBody:描述请求体结构。
  • @ApiResponse:描述响应结构和状态码。

启动项目后,访问 http://localhost:3000/api-docs 即可查看自动生成的接口文档。


实战场景:实现 Hello World 和用户注册

  1. 通过 @Controller()@Get() 实现最基础的 Hello World 接口。
  2. 通过 @Controller('user')@Post('register') 实现用户注册接口,结合 @Body() 获取参数。
  3. 结合 Pipe 实现参数类型转换和校验,提升接口健壮性。
  4. 使用 Swagger 装饰器为接口生成自动化文档,提升团队协作效率。

常见坑点:

  • 忘记在模块(如 app.module.tsuser.module.ts)中注册 Controller,导致接口无法访问。
  • 路由前缀或方法装饰器拼写错误,接口路径不生效。
  • 未正确使用参数装饰器(如 @Body()@Param()),导致参数获取不到。
  • 忘记启用全局校验管道,DTO 校验不生效。
  • 忘记为接口添加 Swagger 装饰器,导致文档不完整或类型不准确。