02 - Nest核心组件

3 阅读5分钟

Nest.js 核心组件详解文档

一、Controller(控制器)

核心职责

  • 请求入口:接收前端发来的 HTTP 请求(GET/POST/PUT/DELETE 等)
  • 路由定义:声明接口路径、请求方法、参数来源(Query/Body/Params)
  • 请求分发:调用对应的 Service 处理业务逻辑
  • 响应处理:接收 Service 处理结果,封装并返回给前端
  • 轻量职责:不写复杂业务逻辑,只做 “请求转发 + 响应封装”

典型代码示例

// src/user/user.controller.ts
import { Controller, Get, Post, Body, Param, Query } from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';

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

  // GET /user/:id - 根据ID查询用户
  @Get(':id')
  async getUserById(@Param('id') id: number) {
    return this.userService.findById(id);
  }

  // POST /user - 创建用户
  @Post()
  async createUser(@Body() createUserDto: CreateUserDto) {
    return this.userService.create(createUserDto);
  }
}

关键特点

  • @Controller() 装饰器声明路由前缀
  • @Get() @Post() 等装饰器声明请求方法和路径
  • 依赖注入 Service,实现业务与请求层解耦

二、Service(服务)

核心职责

  • 业务逻辑实现:处理核心业务(如用户注册校验、订单计算、数据处理)
  • 数据操作:与数据库交互(CRUD)、调用第三方接口、缓存读写
  • 可复用性:被多个 Controller 或其他 Service 调用
  • 单一职责:一个 Service 只负责一个领域的业务(如 UserService 只处理用户相关逻辑)

典型代码示例

// src/user/user.service.ts
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';

@Injectable() // 标记为可注入的服务
export class UserService {
  // 模拟数据库
  private users = [{ id: 1, name: 'admin', email: 'admin@example.com' }];

  // 根据ID查询用户
  async findById(id: number) {
    return this.users.find(user => user.id === id);
  }

  // 创建用户
  async create(createUserDto: CreateUserDto) {
    const newUser = {
      id: this.users.length + 1,
      ...createUserDto
    };
    this.users.push(newUser);
    return newUser;
  }
}

关键特点

  • @Injectable() 装饰器标记,支持依赖注入
  • 可被 Controller、其他 Service、Guard 等注入使用
  • 业务逻辑集中,便于单元测试和维护

三、DTO(数据传输对象)

核心职责

  • 参数格式定义:声明接口入参的字段、类型、是否必填
  • 参数校验:配合 class-validator 实现自动参数校验(如邮箱格式、长度限制)
  • 类型安全:为 TypeScript 提供类型提示,避免参数错误
  • 文档作用:明确接口入参规范,前后端沟通更清晰

典型代码示例

// src/user/dto/create-user.dto.ts
import { IsString, IsEmail, IsInt, Min, MaxLength } from 'class-validator';

export class CreateUserDto {
  // 用户名:字符串,长度2-20
  @IsString()
  @MaxLength(20)
  name: string;

  // 邮箱:必须是合法邮箱格式
  @IsEmail()
  email: string;

  // 年龄:数字,18-100
  @IsInt()
  @Min(18)
  age: number;
}

关键特点

  • 配合 class-validatorclass-transformer 实现自动校验
  • 校验失败会自动返回 400 错误,无需手动写校验逻辑
  • 仅用于接口数据传输,不包含业务逻辑

四、Guard(守卫)

核心职责

  • 权限校验:判断请求是否有权限访问接口(如登录状态、角色权限)
  • 前置拦截:在请求到达 Controller 之前执行,不符合条件直接返回 403/401
  • 全局 / 局部使用:可全局注册,也可在单个 Controller / 方法上使用
  • 灵活控制:支持基于角色、Token、权限的多种校验方式

典型代码示例

// src/common/guards/auth.guard.ts
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    const token = request.headers.authorization;

    // 模拟Token校验
    if (!token || !token.startsWith('Bearer ')) {
      throw new UnauthorizedException('未登录,请先登录');
    }

    // 校验通过
    return true;
  }
}

使用方式

// 在 Controller 上使用(整个控制器的接口都受保护)
@Controller('user')
@UseGuards(AuthGuard)
export class UserController {}

// 在单个方法上使用
@Post()
@UseGuards(AuthGuard)
async createUser(@Body() createUserDto: CreateUserDto) {
  return this.userService.create(createUserDto);
}

关键特点

  • 实现 CanActivate 接口,重写 canActivate 方法
  • 校验失败直接抛出异常,由 Filter 统一处理
  • 不依赖业务逻辑,纯权限控制

五、Filter(异常过滤器)

核心职责

  • 异常捕获:捕获请求处理过程中抛出的所有异常
  • 统一响应格式:将不同类型的异常(如 400/401/403/500)封装成统一的错误响应
  • 日志记录:可在过滤器中记录错误日志,便于排查问题
  • 避免程序崩溃:防止未捕获的异常导致服务中断

典型代码示例

// src/common/filters/http-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch() // 捕获所有异常
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    let status = HttpStatus.INTERNAL_SERVER_ERROR;
    let message = '服务器内部错误';

    // 处理 HttpException 异常
    if (exception instanceof HttpException) {
      status = exception.getStatus();
      const exceptionResponse = exception.getResponse();
      message = typeof exceptionResponse === 'string' 
        ? exceptionResponse 
        : (exceptionResponse as any).message || message;
    }

    // 统一返回错误格式
    response.status(status).json({
      code: status,
      message,
      path: request.url,
      timestamp: new Date().toISOString()
    });
  }
}

注册方式

// src/main.ts 全局注册
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './common/filters/http-exception.filter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalFilters(new HttpExceptionFilter()); // 全局注册异常过滤器
  await app.listen(3000);
}
bootstrap();

关键特点

  • 实现 ExceptionFilter 接口,重写 catch 方法
  • 支持捕获特定类型异常(如 @Catch(HttpException))或所有异常
  • 统一错误响应格式,前端处理更方便

六、Module(模块)

核心职责

  • 业务组织:将同一业务领域的 Controller、Service、DTO 等封装为独立模块(如 UserModule、ProductModule)
  • 依赖管理:声明模块间的依赖关系(如 UserModule 导入 AuthModule)
  • 依赖注入容器:管理模块内所有 Provider(Service、Repository 等)的实例化和生命周期
  • 模块化解耦:模块间相互独立,便于团队协作和代码维护

典型代码示例

// src/user/user.module.ts
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';

@Module({
  controllers: [UserController], // 声明本模块的控制器
  providers: [UserService],       // 声明本模块的服务
  exports: [UserService]          // 导出服务,供其他模块使用
})
export class UserModule {}

根模块 app.module.ts

// src/app.module.ts
import { Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { ProductModule } from './product/product.module';

@Module({
  imports: [UserModule, ProductModule], // 导入业务模块
})
export class AppModule {}

关键特点

  • @Module() 装饰器声明模块配置
  • controllers:注册本模块的控制器
  • providers:注册本模块的服务 / 提供者
  • imports:导入其他模块
  • exports:导出服务供其他模块使用

七、请求完整流程

image.png


八、核心记忆口诀

组件核心作用一句话记忆
Controller接收请求、返回响应接口入口,只管收发
Service实现业务逻辑、数据操作业务干活,处理核心
DTO参数校验、格式定义校验参数,格式规范
Guard权限校验、请求拦截权限看门,校验准入
Filter异常捕获、统一错误响应错误兜底,统一返回
Module模块组织、依赖管理业务打包,依赖容器