NestJS Node 企业级框架

FreeGuideOnline 最新 2026-07-12

bash npm install -g @nestjs/cli


安装完成后,使用 `nest` 命令验证:

```bash
nest --version

创建你的第一个项目

使用 CLI 创建新项目:

nest new project-name

CLI 会询问选择包管理器(npm 或 yarn),随后自动安装依赖。进入项目目录并启动开发服务器:

cd project-name
npm run start:dev

打开浏览器访问 http://localhost:3000,你会看到 Hello World! 的欢迎消息。

理解核心概念

NestJS 应用程序的基石是三个核心概念:模块控制器提供者,它们共同构建出整洁的分层架构。

模块 (Modules)

模块是用 @Module() 装饰器注解的类,用于组织相同功能域的一组组件。每个 NestJS 应用至少有一个根模块 AppModule

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],        // 导入其他模块
  controllers: [AppController], // 该模块拥有的控制器
  providers: [AppService],      // 该模块拥有的提供者
})
export class AppModule {}

控制器 (Controllers)

控制器负责处理传入的 HTTP 请求并返回响应。通过 @Controller() 装饰器和 HTTP 方法装饰器(@Get@Post 等)定义路由。

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

@Controller('cats')   // 路由前缀 /cats
export class CatsController {
  constructor(private readonly appService: AppService) {}

  @Get()
  findAll(): string {
    return this.appService.getHello();
  }
}

提供者 (Providers) 与依赖注入

提供者是可以被注入的对象,通常是服务类。它们用 @Injectable() 装饰器标记,并通过构造器注入到控制器或其他提供者中。

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

NestJS 的 IoC 容器会自动管理这些实例的创建与生命周期,确保单一实例(默认)在多处共享。

构建 RESTful API

路由与请求处理

常用的装饰器包括:

装饰器 说明
@Get() 处理 GET 请求
@Post() 处理 POST 请求
@Put() 处理 PUT 请求
@Delete() 处理 DELETE 请求
@Param() 获取路径参数,例如 /cats/:id
@Query() 获取查询字符串参数
@Body() 获取请求体(POST/PUT)

创建 CRUD 示例

我们以“猫咪”资源为例,创建一个完整的增删改查。

1. 生成模块、控制器和服务

nest generate module cats
nest generate controller cats
nest generate service cats

2. 定义数据传输对象 (DTO)

创建 create-cat.dto.ts

export class CreateCatDto {
  name: string;
  age: number;
  breed: string;
}

3. 实现服务 (cats.service.ts)

import { Injectable } from '@nestjs/common';
import { CreateCatDto } from './create-cat.dto';

@Injectable()
export class CatsService {
  private readonly cats: CreateCatDto[] = [];

  create(cat: CreateCatDto) {
    this.cats.push(cat);
  }

  findAll(): CreateCatDto[] {
    return this.cats;
  }

  findOne(id: number): CreateCatDto {
    return this.cats[id];
  }
}

4. 实现控制器 (cats.controller.ts)

import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { CatsService } from './cats.service';
import { CreateCatDto } from './create-cat.dto';

@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Post()
  create(@Body() createCatDto: CreateCatDto) {
    this.catsService.create(createCatDto);
    return '猫咪已添加';
  }

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

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

现在你可以通过 POST /cats 添加猫咪,GET /cats 获取列表,GET /cats/1 获取单个猫咪。

进阶特性

中间件

中间件是在请求进入路由处理程序之前执行的函数,可用于日志记录、CORS 设置等。实现 NestMiddleware 接口。

import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    console.log(`Request... ${req.method} ${req.url}`);
    next();
  }
}

在模块中应用:

export class CatsModule implements NestMiddleware {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes('cats');
  }
}

异常过滤器

内置的异常层负责处理应用中抛出的所有异常。你也可以创建自定义异常过滤器,用于改写错误响应格式。

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      message: exception.message,
    });
  }
}

在控制器或全局应用:

@UseFilters(new HttpExceptionFilter())
@Controller('cats')
export class CatsController { ... }

管道 (Pipes)

管道用于转换验证输入数据。例如,内置的 ValidationPipe 配合 class-validator 可以自动校验请求体。

安装依赖:

npm install class-validator class-transformer

main.ts 中全局启用:

app.useGlobalPipes(new ValidationPipe());

DTO 中添加验证规则:

import { IsString, IsInt } from 'class-validator';

export class CreateCatDto {
  @IsString()
  name: string;

  @IsInt()
  age: number;

  @IsString()
  breed: string;
}

守卫 (Guards)

守卫用于决定请求是否由路由处理程序处理,常用于权限认证。实现 CanActivate 接口。

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    return request.headers.authorization === 'secret';
  }
}

在控制器或路由上使用 @UseGuards(AuthGuard)

拦截器 (Interceptors)

拦截器可以在方法执行前后添加额外逻辑,例如统一响应格式、日志记录、缓存等。

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable()
export class TransformInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(map(data => ({ code: 0, data })));
  }
}

全局应用:app.useGlobalInterceptors(new TransformInterceptor())

数据库集成

通常企业级应用需要持久化存储。NestJS 官方推荐使用 TypeORM 或 Prisma。以 TypeORM 为例:

安装依赖:

npm install @nestjs/typeorm typeorm mysql2

在根模块中配置连接:

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [Cat],
      synchronize: true, // 生产环境务必关闭
    }),
  ],
})
export class AppModule {}

定义实体并使用 @nestjs/typeormInjectRepository 装饰器在服务中操作数据库。详细使用可参考 TypeORM 官方文档。

测试

Nest 内置 Jest,可通过 CLI 一键生成测试文件。

npm run test        # 单元测试
npm run test:e2e    # 端到端测试

示例:测试 CatsController。

describe('CatsController', () => {
  let controller: CatsController;
  let service: CatsService;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      controllers: [CatsController],
      providers: [CatsService],
    }).compile();

    controller = module.get(CatsController);
    service = module.get(CatsService);
  });

  it('should return an array of cats', () => {
    jest.spyOn(service, 'findAll').mockImplementation(() => [{ name: 'Kitty', age: 2, breed: '未知' }]);
    expect(controller.findAll()).toEqual([{ name: 'Kitty', age: 2, breed: '未知' }]);
  });
});