阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > NestJS架构

NestJS架构

作者:陈川 阅读数:33364人阅读 分类: Node.js

NestJS 是一个基于 Node.js 的渐进式框架,用于构建高效、可扩展的服务器端应用程序。它采用模块化设计,结合了面向对象编程、函数式编程和响应式编程的优势,同时底层默认集成 Express 或 Fastify,为开发者提供了灵活的选择。

核心架构设计

NestJS 的核心架构建立在几个关键概念之上:

  1. 模块系统:应用程序被组织成模块,每个模块封装特定功能
  2. 依赖注入:通过装饰器实现松耦合的组件管理
  3. 控制器:处理 HTTP 请求并返回响应
  4. 提供者:可注入的服务、仓库等业务逻辑组件
  5. 中间件:处理请求/响应周期的功能
  6. 异常过滤器:集中处理应用程序异常
  7. 管道:数据验证和转换
  8. 守卫:路由访问控制
  9. 拦截器:在方法执行前后添加额外逻辑

模块系统详解

模块是 NestJS 应用的基本组织单元,使用 @Module() 装饰器定义:

@Module({
  imports: [OtherModule],
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService]
})
export class UserModule {}
  • imports:导入其他模块
  • controllers:注册控制器
  • providers:注册提供者(服务)
  • exports:暴露提供者给其他模块使用

依赖注入机制

NestJS 的依赖注入系统是其架构的核心优势。通过构造函数注入的方式实现:

@Injectable()
export class UserService {
  constructor(private readonly repository: UserRepository) {}
  
  async findAll(): Promise<User[]> {
    return this.repository.find();
  }
}

在控制器中使用服务:

@Controller('users')
export class UserController {
  constructor(private readonly userService: UserService) {}
  
  @Get()
  async findAll(): Promise<User[]> {
    return this.userService.findAll();
  }
}

控制器与路由

控制器负责处理传入请求并返回响应:

@Controller('cats')
export class CatsController {
  @Get()
  findAll(): string {
    return 'This action returns all cats';
  }

  @Get(':id')
  findOne(@Param('id') id: string): string {
    return `This action returns a #${id} cat`;
  }

  @Post()
  @HttpCode(204)
  create() {
    return 'This action adds a new cat';
  }
}

提供者与服务

提供者是 NestJS 中业务逻辑的主要承载者:

@Injectable()
export class NotificationService {
  private readonly clients: Client[] = [];

  addClient(client: Client) {
    this.clients.push(client);
  }

  sendAll(message: string) {
    this.clients.forEach(client => client.send(message));
  }
}

中间件系统

中间件可以处理请求和响应:

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`Request... ${req.method} ${req.path}`);
    next();
  }
}

在模块中应用:

export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('*');
  }
}

异常处理

NestJS 提供了异常过滤器机制:

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

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

在控制器中使用:

@Post()
@UseFilters(new HttpExceptionFilter())
async create(@Body() createCatDto: CreateCatDto) {
  throw new ForbiddenException();
}

管道与数据验证

管道用于数据转换和验证:

@Injectable()
export class ValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    if (!value) {
      throw new BadRequestException('No data submitted');
    }
    return value;
  }
}

使用内置的验证管道:

@Post()
async create(
  @Body(new ValidationPipe()) createUserDto: CreateUserDto
) {
  // ...
}

守卫与认证

守卫用于路由访问控制:

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

在控制器中使用:

@UseGuards(AuthGuard)
@Controller('profile')
export class ProfileController {}

拦截器

拦截器可以在方法执行前后添加逻辑:

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('Before...');
    const now = Date.now();
    return next
      .handle()
      .pipe(tap(() => console.log(`After... ${Date.now() - now}ms`)));
  }
}

应用拦截器:

@UseInterceptors(LoggingInterceptor)
@Controller('users')
export class UserController {}

微服务支持

NestJS 原生支持微服务架构:

const app = await NestFactory.createMicroservice<MicroserviceOptions>(
  AppModule,
  {
    transport: Transport.TCP,
    options: { host: 'localhost', port: 3001 }
  }
);
await app.listen();

WebSocket 集成

NestJS 提供了对 WebSocket 的良好支持:

@WebSocketGateway()
export class EventsGateway {
  @WebSocketServer()
  server: Server;

  @SubscribeMessage('events')
  handleEvent(client: any, data: string): string {
    return data;
  }
}

测试策略

NestJS 提供了完善的测试工具:

describe('UserController', () => {
  let userController: UserController;
  let userService: UserService;

  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      controllers: [UserController],
      providers: [UserService],
    }).compile();

    userService = moduleRef.get<UserService>(UserService);
    userController = moduleRef.get<UserController>(UserController);
  });

  describe('findAll', () => {
    it('should return an array of users', async () => {
      const result = ['test'];
      jest.spyOn(userService, 'findAll').mockImplementation(() => result);
      expect(await userController.findAll()).toBe(result);
    });
  });
});

配置管理

NestJS 推荐使用 ConfigModule 进行配置管理:

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: '.development.env',
    }),
  ],
})
export class AppModule {}

使用配置:

@Injectable()
export class DatabaseService {
  constructor(private configService: ConfigService) {
    const dbUser = this.configService.get<string>('DATABASE_USER');
  }
}

数据库集成

NestJS 支持多种 ORM 集成,以 TypeORM 为例:

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'postgres',
      password: 'postgres',
      database: 'test',
      entities: [User],
      synchronize: true,
    }),
    TypeOrmModule.forFeature([User]),
  ],
})
export class AppModule {}

定义实体:

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

  @Column()
  firstName: string;

  @Column()
  lastName: string;
}

性能优化

NestJS 应用可以通过多种方式优化性能:

  1. 使用 FastifyAdapter 替代默认的 Express
  2. 实现缓存策略
  3. 使用压缩中间件
  4. 启用集群模式
  5. 优化依赖注入树

启用 Fastify:

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter()
  );
  await app.listen(3000);
}

部署策略

NestJS 应用可以部署在各种环境中:

  1. 传统服务器部署
  2. 容器化部署(Docker)
  3. 无服务器架构(Serverless)
  4. 平台即服务(PaaS)

Docker 部署示例:

FROM node:16-alpine

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

EXPOSE 3000
CMD ["node", "dist/main"]

生态系统与插件

NestJS 拥有丰富的生态系统:

  1. @nestjs/swagger - API 文档生成
  2. @nestjs/graphql - GraphQL 支持
  3. @nestjs/bull - 队列处理
  4. @nestjs/terminus - 健康检查
  5. @nestjs/schedule - 任务调度

Swagger 集成示例:

const config = new DocumentBuilder()
  .setTitle('Cats example')
  .setDescription('The cats API description')
  .setVersion('1.0')
  .addTag('cats')
  .build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);

架构最佳实践

  1. 遵循单一职责原则设计模块
  2. 使用领域驱动设计(DDD)组织代码结构
  3. 实现清晰的层次划分(控制器-服务-仓库)
  4. 保持业务逻辑与框架解耦
  5. 编写全面的单元测试和集成测试

领域驱动设计示例结构:

src/
├── users/
│   ├── entities/
│   ├── repositories/
│   ├── services/
│   ├── controllers/
│   └── users.module.ts
├── products/
│   ├── entities/
│   ├── repositories/
│   ├── services/
│   ├── controllers/
│   └── products.module.ts
└── shared/
    ├── infrastructure/
    └── common/

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:Koa与中间件机制

下一篇:GraphQL实现

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌