• 作者:老汪软件技巧
  • 发表时间:2024-09-26 07:01
  • 浏览量:

1. 前言

之前使用控制器来实现 CRUD 的基本功能,本节将重点介绍 NestJS 中的服务类(service 文件),它主要用于处理业务逻辑。一般来说,它将包含应用程序的核心功能,并负责与数据库、其他服务、外部 API 或是第三方库交互。

目前的代码结构如下:

欢迎加入技术交流群。

NestJS ‍ 厨子必修课(一):后端的本质NestJS ‍厨子必修课(二):项目创建NestJS ‍厨子必修课(三):控制器NestJS ‍厨子必修课(四):服务类NestJS ‍厨子必修课(五):Prisma 集成(上)2. 提供器

作为一个松耦合的设计来说,带有 @Injectable 装饰器的服务类作为依赖项(提供器)被注入到控制器中,使得控制类更为强大。

举个例子,在这层关系中,服务类属于(疫苗)提供者进行注入(),作为注入目标的控制类(人类)则是消费者,消费者功能增强了(人类具备病毒免疫力)。

2.1 服务类定义

menus.service.ts 的代码主体结构如下:

import { Injectable } from '@nestjs/common';
// ...
@Injectable()
export class MenusService {
  // ...
}

@Injectable 装饰器用于标记 MenusService 类为可注入的提供器,它告诉 NestJS 这个类可以作为一个提供器使用,并且可以被其他类(如控制器、服务、模块等)通过构造函数注入。

2.2 服务类注入

这样,它就可以在 menu.controller.ts 中的 MenusController 类中的构造函数中注入:

// ...
import { MenusService } from './menus.service';
@Controller('menus')
export class MenusController {
  constructor(private readonly menusService: MenusService) {}
  // CRUD 相关业务逻辑代码
}

于是,访问对应 api 接口就能调用服务类中的方法,进而返回数据给前端。

2.3 服务注册

整体来说,对菜单的 CRUD 是一项服务,它有提供者、消费者,自然也需要一个中心组织来管理它们,这就是 menus 目录下的 module 文件 —— menus.module.ts,在这里,我们把控制类和服务类注册上去:

import { Module } from '@nestjs/common';
import { MenusService } from './menus.service';
import { MenusController } from './menus.controller';
@Module({
  controllers: [MenusController], // 控制器
  providers: [MenusService], // 提供器(服务)
})
export class MenusModule {}

@Module 装饰器用于定义 MenusModule 类为一个模块。模块是 NestJS 应用程序的基本构建块,用于组织和封装一组相关的组件(如提供器、控制器、导入的模块等)。上面就是一个有关 menus 的模块,它可以作为一个单元被导入导出。

除了 controllers 用于注册控制器、providers 用于注册提供器,@Module 中还有:

⚠️注意:如果不进行注册,这些依赖就不会得到解析。

3. 主模块

app.module.ts 是主模块所在文件,这是整个系统的核心所在,可以看作是中央大脑。

箭头表示导入方向,比如共享模块被导入到各个服务类中,各个服务类分别导入对应的功能模块中,功能模块导入主模块。共享模块将在以后提到。

3.1 menus 模块导入到主模块

menus 模块作为子模块需要导入到主模块 app.module.ts 中:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MenusModule } from './menus/menus.module';
@Module({
  imports: [MenusModule], // 导入 MenusModule 模块
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

通过 imports: [MenusModule] 将 MenusModule 导入到主模块,这样 AppModule 可以使用 MenusModule 中定义的所有功能了。

3.2 main.ts 启动应用

main.ts 为整个应用的入口文件:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

在这里调用 bootstrap 方法:将主模块 AppModule 传入 NestJS 的工厂函数 NestFactory.create 方法就能创建一个 Nest 应用实例,最后将在 3000 端口启动。

4. 总结

在 NestJS 应用架构中,控制器负责接收和处理 HTTP 请求,随后将业务逻辑的处理工作委托给服务类。这些服务类通过依赖注入机制与控制器相连,确保了代码的松耦合和可维护性。服务类随后在各自的模块中注册,并通过模块化结构向上聚合,直至达到应用的根模块。这种分层和模块化的策略构建了一个清晰、高效的服务架构,为应用程序的运行提供了坚实的基础。