Skip to content
On this page

NestJS架构

NestJS采用模块化的架构模式,借鉴了Angular的设计理念,使得应用程序结构清晰、可维护性强。本章详细介绍NestJS的架构模式和组件。

应用程序架构

三层架构模式

NestJS应用程序通常遵循经典的三层架构:

┌─────────────────┐
│   Presentation  │  ← 控制器 (Controllers)
├─────────────────┤
│   Business Logic│  ← 服务/提供者 (Services/Providers)  
├─────────────────┤
│   Data Access   │  ← 数据库、外部服务 (Database/External APIs)
└─────────────────┘

模块化架构

NestJS采用模块化的架构,每个模块负责特定的功能:

typescript
// app.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';
import { PostsModule } from './posts/posts.module';
import { DatabaseModule } from './database/database.module';

@Module({
  imports: [
    DatabaseModule,
    UsersModule,
    PostsModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

模块 (Modules)

模块定义

模块是带有@Module()装饰器的类,用于组织应用程序的组件:

typescript
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService], // 导出服务供其他模块使用
})
export class CatsModule {}

模块元数据

@Module()装饰器接受以下元数据:

  • providers - 由Nest注入器实例化的提供者,并至少在该模块中可用
  • controllers - 应该被实例化的控制器列表
  • imports - 导入模块列表,这些模块导出的提供者在此模块中需要
  • exports - 导出提供者的子集,这些提供者在其他模块中可用
  • module - 可选的模块类引用
  • scope - 模块注入范围

核心模块

typescript
// core/core.module.ts
import { Module, Global } from '@nestjs/common';
import { LoggerService } from './logger.service';
import { ConfigService } from './config.service';

@Global() // 全局模块
@Module({
  providers: [
    LoggerService,
    ConfigService,
  ],
  exports: [
    LoggerService,
    ConfigService,
  ],
})
export class CoreModule {}

功能模块

typescript
// users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { DatabaseModule } from '../database/database.module';
import { LoggerService } from '../core/logger.service';

@Module({
  imports: [DatabaseModule], // 导入依赖模块
  controllers: [UsersController],
  providers: [
    UsersService,
    LoggerService, // 局部提供者
  ],
  exports: [UsersService], // 导出供其他模块使用
})
export class UsersModule {}

控制器 (Controllers)

控制器定义

控制器负责处理传入的请求和返回响应给客户端:

typescript
import { 
  Controller, 
  Get, 
  Post, 
  Put, 
  Delete, 
  Param, 
  Body, 
  Query,
  HttpStatus,
  HttpCode,
  Header,
  Res,
  UseGuards,
  UseInterceptors,
  UsePipes,
  UseFilters
} from '@nestjs/common';
import { Response } from 'express';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { ValidationPipe } from '../pipes/validation.pipe';
import { RolesGuard } from '../guards/roles.guard';
import { LoggingInterceptor } from '../interceptors/logging.interceptor';
import { HttpExceptionFilter } from '../filters/http-exception.filter';

@Controller('users')
@UseGuards(RolesGuard) // 应用守卫
@UseInterceptors(LoggingInterceptor) // 应用拦截器
@UsePipes(ValidationPipe) // 应用管道
@UseFilters(HttpExceptionFilter) // 应用过滤器
export class UsersController {
  constructor(private usersService: UsersService) {}

  @Get()
  @HttpCode(HttpStatus.OK)
  @Header('Cache-Control', 'max-age=3600')
  async findAll(@Query() query: any): Promise<any[]> {
    return this.usersService.findAll(query);
  }

  @Get(':id')
  @UseGuards(RolesGuard) // 在特定方法上应用守卫
  async findOne(@Param('id') id: string): Promise<any> {
    return this.usersService.findOne(id);
  }

  @Post()
  @HttpCode(HttpStatus.CREATED)
  async create(@Body() createUserDto: CreateUserDto): Promise<any> {
    return this.usersService.create(createUserDto);
  }

  @Put(':id')
  async update(
    @Param('id') id: string, 
    @Body() updateUserDto: any
  ): Promise<any> {
    return this.usersService.update(id, updateUserDto);
  }

  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  async remove(@Param('id') id: string): Promise<void> {
    await this.usersService.remove(id);
  }

  @Get('stream/:id')
  async stream(@Param('id') id: string, @Res() res: Response) {
    const user = await this.usersService.findOne(id);
    res.status(HttpStatus.OK).json(user);
  }
}

服务和提供者 (Services and Providers)

服务定义

服务是处理业务逻辑的类:

typescript
import { Injectable, Inject, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';
import { DatabaseService } from '../database/database.service';
import { LoggerService } from '../core/logger.service';

@Injectable() // 标记为可注入的服务
export class UsersService {
  constructor(
    private databaseService: DatabaseService,
    private loggerService: LoggerService,
  ) {}

  async findAll(query: any): Promise<any[]> {
    this.loggerService.log('Finding all users', 'UsersService');
    return this.databaseService.find('users', query);
  }

  async findOne(id: string): Promise<any> {
    this.loggerService.log(`Finding user with id: ${id}`, 'UsersService');
    return this.databaseService.findOne('users', id);
  }

  async create(userData: any): Promise<any> {
    this.loggerService.log('Creating user', 'UsersService');
    return this.databaseService.create('users', userData);
  }

  async update(id: string, userData: any): Promise<any> {
    this.loggerService.log(`Updating user with id: ${id}`, 'UsersService');
    return this.databaseService.update('users', id, userData);
  }

  async remove(id: string): Promise<void> {
    this.loggerService.log(`Removing user with id: ${id}`, 'UsersService');
    await this.databaseService.delete('users', id);
  }
}

请求范围的服务

typescript
import { Injectable, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';

@Injectable({ scope: Scope.REQUEST }) // 请求范围的服务
export class RequestContextService {
  constructor(@Inject(REQUEST) private request: Request) {}

  getRequestId(): string {
    return this.request.headers['x-request-id'] as string || 'unknown';
  }

  getUserFromRequest(): any {
    return this.request.user;
  }
}

分层架构最佳实践

数据传输对象 (DTOs)

typescript
// dto/create-user.dto.ts
import { IsString, IsEmail, IsNumber, Min, Max } from 'class-validator';

export class CreateUserDto {
  @IsString()
  readonly name: string;

  @IsEmail()
  readonly email: string;

  @IsNumber()
  @Min(0)
  @Max(120)
  readonly age: number;
}

// dto/update-user.dto.ts
import { PartialType } from '@nestjs/mapped-types';
import { CreateUserDto } from './create-user.dto';

export class UpdateUserDto extends PartialType(CreateUserDto) {}

实体 (Entities)

typescript
// entities/user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column({ unique: true })
  email: string;

  @Column()
  password: string;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;
}

模块依赖关系

循环依赖处理

typescript
// users/users.module.ts
import { Module, forwardRef } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { AuthModule } from '../auth/auth.module';

@Module({
  imports: [
    forwardRef(() => AuthModule), // 处理循环依赖
  ],
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

共享模块

typescript
// shared/shared.module.ts
import { Module, Global } from '@nestjs/common';
import { CacheService } from './cache/cache.service';
import { LoggingService } from './logging/logging.service';
import { ValidationService } from './validation/validation.service';

@Global() // 全局共享模块
@Module({
  providers: [
    CacheService,
    LoggingService,
    ValidationService,
  ],
  exports: [
    CacheService,
    LoggingService,
    ValidationService,
  ],
})
export class SharedModule {}

微服务架构

微服务模块

typescript
// microservices/users-ms.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { UsersMsService } from './users-ms.service';

@Module({
  imports: [
    ClientsModule.register([
      {
        name: 'USER_SERVICE',
        transport: Transport.TCP,
        options: {
          host: 'localhost',
          port: 8877,
        },
      },
    ]),
  ],
  providers: [UsersMsService],
  exports: [UsersMsService],
})
export class UsersMsModule {}

应用程序引导

主入口点

typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from './pipes/validation.pipe';
import { HttpExceptionFilter } from './filters/http-exception.filter';
import { LoggingInterceptor } from './interceptors/logging.interceptor';
import { TimeoutInterceptor } from './interceptors/timeout.interceptor';

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

  // 全局中间件
  app.useGlobalFilters(new HttpExceptionFilter());
  app.useGlobalPipes(new ValidationPipe());
  app.useGlobalInterceptors(
    new LoggingInterceptor(),
    new TimeoutInterceptor(),
  );

  // 其他配置
  app.setGlobalPrefix('api');
  app.enableCors();

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

架构模式

仓储模式

typescript
// repositories/user.repository.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '../entities/user.entity';

@Injectable()
export class UserRepository {
  constructor(
    @InjectRepository(User)
    private userRepository: Repository<User>,
  ) {}

  async findAll(): Promise<User[]> {
    return this.userRepository.find();
  }

  async findById(id: number): Promise<User> {
    return this.userRepository.findOne({ where: { id } });
  }

  async create(user: User): Promise<User> {
    return this.userRepository.save(user);
  }

  async update(id: number, user: User): Promise<User> {
    await this.userRepository.update(id, user);
    return this.findById(id);
  }

  async delete(id: number): Promise<void> {
    await this.userRepository.delete(id);
  }
}

仓库模式的模块

typescript
// users/users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from '../entities/user.entity';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { UserRepository } from '../repositories/user.repository';

@Module({
  imports: [
    TypeOrmModule.forFeature([User]), // 注册实体
  ],
  controllers: [UsersController],
  providers: [
    UsersService,
    UserRepository, // 注册仓储
  ],
  exports: [UsersService],
})
export class UsersModule {}

NestJS的架构设计遵循了关注点分离和单一职责原则,使得应用程序易于测试、维护和扩展。