theme: fancy
highlight: atelier-dune-dark

前言

模块指的是使用@Module装饰器修饰的类,每个应用程序至少有一个模块,即根模块。根模块是Nest用于构建应用程序的起点,理论上Nest程序可能只有根模块,但在大多数情况下是存在多个模块的,每个模块各自封装一组相关的功能。

@Module装饰器

@Module()装饰器可以传入一个对象,属性值如下:

providers 将由 Nest 注入器实例化的提供程序,并且至少可以在该模块中共享
controllers 该模块中定义的必须实例化的控制器集
imports 导入模块的列表,导出该模块所需的提供程序
exports 该子集providers由该模块提供,并且应该在导入该模块的其他模块中可用
@Module({
imports: [NanjiuModule, UserModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

模块共享

如果你想把当前模块的service暴露给其它模块使用,则可以使用exports到处该服务

比如我使用nest g resource info新建了一个info类,并且使用export导出该服务

// info.module.ts
import { Module } from '@nestjs/common';
import { InfoService } from './info.service';
import { InfoController } from './info.controller'; @Module({
controllers: [InfoController],
providers: [InfoService], // 提供者
exports: [InfoService] // 导出 InfoService 供其他模块使用
})
export class InfoModule {}

然后我在user模块中使用imports导入该模块

// user.module.ts
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { InfoModule } from 'src/info/info.module'; @Module({
imports: [InfoModule], // 导入 InfoModule
controllers: [UserController],
providers: [UserService]
})
export class UserModule {}

最后在controller中依赖注入并使用

// user.controller.ts
import { InfoService } from 'src/info/info.service'; @Controller('user')
export class UserController {
constructor(
private readonly userService: UserService,
private readonly infoService: InfoService, // 注入 InfoService
) {} @Post()
create(@Body() createUserDto: CreateUserDto) {
return this.infoService.findAll() // 调用 InfoService 的 findAll 方法 // return this.userService.create(createUserDto);
}
//...
}

这样就完成模块共享了,可以看到我们在user模块中可以调用info的服务

模块再导出

可以把一些常用的,公共的模块,全部先import进一个CommonModule,然后再把它们从exprots全部导出,以后如果有那个模块想要使用其中某个模块的Service,只需要将这个CommonModule导入即可,不用再导入所有的依赖模块

// common.module.ts
@Module({
imports: [Module1, Module2, Module3, Module4],
exports: [Module1, Module2, Module3, Module4],
})
export class CommonModule {}

依赖注入

模块类也可以注入provider服务


@Module({
controllers: [UserController],
providers: [UserService],
})
export class UserModule {
constructor(private userService: UserService) {}
}

全局模块

通过@Global()装饰器声明一个全局模块,只需要在根模块imports注册该全局模块,就可以在其他所有模块内使用它导出的Service

比如:将info声明为全局模块

// info.module.ts
@Global() // 全局模块
@Module({
controllers: [InfoController],
providers: [InfoService], // 提供者
exports: [InfoService] // 导出 InfoService 供其他模块使用
})
export class InfoModule {}

然后在user模块中无需导入,只需依赖注入就可直接使用(前提是已在根模块导入)

// user.controller.ts
import { CreateUserDto } from './dto/create-user.dto';
import { InfoService } from 'src/info/info.service'; @Controller('user')
export class UserController {
constructor(
private readonly userService: UserService,
private readonly infoService: InfoService, // 注入 InfoService
) {} @Post()
create(@Body() createUserDto: CreateUserDto) {
return this.infoService.findAll() // 调用 InfoService 的 findAll 方法
}
}

动态模块

动态模块能够让我们创建可定制的模块,当导入模块并向其传入某些选项参数,这个模块根据这些选项参数来动态的创建不同特性的模块。

创建动态模块

动态模块其实就是给当前Module类提供一个forRoot方法,该方法返回一个新的Module,这个Module的类型是一个DynamicModule,在其他模块需要注册使用时,可以使用xxxModule.forRoot(args)来动态的注册不同的Module,以达到提供不同providers的目的。

这里我们创建一个config的动态模块

// config.module.ts
import { Module, DynamicModule, Global } from '@nestjs/common';
import { NanjiuService } from 'src/nanjiu/nanjiu.service';
import { UserService } from 'src/user/user.service'; interface Options {
name: string
}
@Global()
@Module({
})
export class ConfigModule {
static forRoot(options: Options): DynamicModule {
console.log('options', options)
return {
module: ConfigModule,
providers: [
{provide: 'config', useClass: options.name === 'nanjiu' ? NanjiuService : UserService},
],
exports: [
{provide: 'config', useClass: options.name === 'nanjiu' ? NanjiuService : UserService}
]
}
}
}

这个例子很简单,首先需要自己编写一个静态方法,该方法通过接收传递进来的参数判断使用哪一个service,并且为了方便,我这里直接使用@Global()装饰器将该模块声明称了全局模块

传递参数使用

调用静态方法传递参数

// app.module.ts
@Module({
imports: [ConfigModule.forRoot({name: 'fe'})],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

然后在controller中使用

import { Controller, Get, Inject } from '@nestjs/common';
import { AppService } from './app.service'; @Controller()
export class AppController {
constructor(
private readonly appService: AppService,
@Inject('config') private readonly configService // 注入 ConfigService
) {} @Get('/hello2')
get2() {
return this.configService.getHello() // 调用 ConfigService 的 getHello 方法
}
}

比如上面forRoot传递的参数是{name: 'nanjiu'},所以此时的ConfigModule注入的应该是UserService

修改forRoot参数

// app.module.ts
@Module({
imports: [ConfigModule.forRoot({name: 'nanjiu'})],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

此时通过get方式再访问同样的路由,应该是访问到NanjiuService提供的服务了。

以上就是动态模块的简单用法,后续内容我们还会再遇到它~

【NestJS系列】核心概念:Module模块的更多相关文章

  1. Spark系列-核心概念

    Spark系列-初体验(数据准备篇) Spark系列-核心概念 一. Spark核心概念 Master,也就是架构图中的Cluster Manager.Spark的Master和Workder节点分别 ...

  2. ZooKeeper 系列(一)—— ZooKeeper核心概念详解

    一.Zookeeper简介 二.Zookeeper设计目标 三.核心概念         3.1 集群角色         3.2 会话         3.3 数据节点         3.4 节点 ...

  3. ZooKeeper系列(一)—— ZooKeeper 简介及核心概念

    一.Zookeeper简介 Zookeeper 是一个开源的分布式协调服务,目前由 Apache 进行维护.Zookeeper 可以用于实现分布式系统中常见的发布/订阅.负载均衡.命令服务.分布式协调 ...

  4. Storm 系列(二)—— Storm 核心概念详解

    一.Storm核心概念 1.1 Topologies(拓扑) 一个完整的 Storm 流处理程序被称为 Storm topology(拓扑).它是一个是由 Spouts 和 Bolts 通过 Stre ...

  5. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

  6. [程序设计语言]-[核心概念]-02:名字、作用域和约束(Bindings)

    本系列导航 本系列其他文章目录请戳这里. 1.名字.约束时间(Binding Time) 在本篇博文开始前先介绍两个约定:第一个是“对象”,除非在介绍面向对象语言时,本系列中出现的对象均是指任何可以有 ...

  7. Maven介绍,包括作用、核心概念、用法、常用命令、扩展及配置

    由浅入深,主要介绍maven的用途.核心概念(Pom.Repositories.Artifact.Build Lifecycle.Goal).用法(Archetype意义及创建各种项目).maven常 ...

  8. webpack的四个核心概念介绍

    前言 webpack 是一个当下最流行的前端资源的模块打包器.当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后 ...

  9. webpack核心概念

    一.webpack四个核心概念 1.入口[Entry] webpack将创建所有应用程序 依赖关系图表.图表的起点被称之为 入口起点.入口起点告诉webpack从哪里开始,并遵循着依赖关系图表知道打包 ...

  10. Redux 核心概念

    http://gaearon.github.io/redux/index.html ,文档在 http://rackt.github.io/redux/index.html .本文不是官方文档的翻译. ...

随机推荐

  1. MySQL的varchar存储原理:InnoDB记录存储结构

    摘要:varchar(M) 能存多少个字符,为什么提示最大16383?innodb怎么知道varchar真正有多长?记录为NULL,innodb如何处理?某个列数据占用的字节数非常多怎么办?影响每行实 ...

  2. Django4全栈进阶之路12 render 函数和 redirect 函数

    在 Django 中,你可以使用 render 函数来渲染模板并将其返回给客户端,也可以使用 redirect 函数来重定向到其他 URL. 在 Django 中,render 函数和 redirec ...

  3. yaml的读写

    yaml文件的读写是真的快,也很简单.代码如下:from ruamel.yaml import YAMLimport os # 读取yaml配置文件def read_yaml(yaml_path): ...

  4. 代码随想录算法训练营Day31 贪心算法| 理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和

    代码随想录算法训练营 理论基础 什么是贪心 贪心的本质是选择每一阶段的局部最优,从而达到全局最优. 每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优. 贪心的套路(什么时候用贪心) 贪心 ...

  5. 【python基础】基本数据类型-数字类型

    Python3 支持int(整型数据).float(浮点型数据).bool(布尔类型) 1.int(整型数据) 在Python 3里,只有一种整数类型 int,表示为长整型.像大多数语言一样,数值类型 ...

  6. 美女同事的烦恼:如何配置 Apache SkyWalking 告警?

    小婉 技术部基本上是一个和尚庙,女生非常少,即使有女生也略微有点抽象,小婉就不一样,她气质绝佳. 上午,同事小婉刚才从老板办公室里出来,看上去一脸不悦的样子.为了表示对同事的关(ba)心(gua),我 ...

  7. HyperPlatform

    之前也写过一个vt的框架,但是比较简单,写的比较乱迁移什么的比较麻烦,于是阅读下HyperPlatform的源码学习下. 本文只对主体框架分析. vt的流程大概如下 1:检测是否支持VT. 2:vmx ...

  8. 【LeetCode】Find Pivot Index #724 Rust Solution

    给定一个整数类型的数组 nums,请编写一个能够返回数组 "中心索引" 的方法.我们是这样定义数组 中心索引 的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和.如果数 ...

  9. 安装部署 Kubernetes 仪表板(Dashboard)

    简介 Kubernetes 仪表板(Dashboard)是基于网页的 Kubernetes 用户界面. 你可以使用仪表板: 展示了 Kubernetes 集群中的资源状态信息和所有报错信息. 把容器应 ...

  10. GPT3的局限性:语言多样性、语言理解能力、数据量

    目录 GPT-3 的局限性:语言多样性.语言理解能力.数据量 随着人工智能技术的不断发展,越来越多的语言模型被开发出来,其中最具代表性的就是 GPT-3.然而,尽管 GPT-3 已经在自然语言处理领域 ...