第十一章 Nest 创建动态模块

在 NestJS 中,动态模块允许在运行时动态添加和删除模块。这对于创建可扩展的和灵活的应用程序非常有用。

新建一个项目:

nest new dynamic-module -p npm

1717907361646.png
创建一个crud的模块:

nest g resource test

1717907490721.png
启动项目 浏览器访问 可以发现模块生效了

pnpm run start:dev

1717907603268.png
1717907581969.png
但是这个模块目前是静态的 内容固定不变 当我们想在mport 的时候给这个模块传一些参数,动态生成模块的内容 就可以使用 Dynamic Module动态模块
修改 test.module.ts: 给 TestModule 加一个 register 的静态方法,返回模块定义的对象

import { DynamicModule, Module } from '@nestjs/common';
import { TestService } from './test.service';
import { TestController } from './test.controller';

@Module({
})
export class TestModule {
  static register(options: Record<string, any>): DynamicModule {
    return {
      module: TestModule,
      providers: [
        {
          provide: 'TEST_OPTIONS',
          useValue: options
        },
        TestService
      ],
      exports: [TestService]
    }
  }
}

接着在 app.module.ts 使用

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

@Module({
  imports: [TestModule.register({ test: '666' })],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }

最后在 test.controller.ts打印

constructor(private readonly testService: TestService,
    @Inject('TEST_OPTIONS') private configOptions: Record<string, any>) { }
@Get()
  findAll() {
    console.log(this.configOptions);

    return this.testService.findAll();
  }

1717912063418.png
启动项目

pnpm run start:dev

访问 http://localhost:3000/test 可以看到控制台打印了 config 对象信息
1717912420117.png
这样我们就可以在 import 一个模块的时候,传入参数,然后动态生成模块的内容。

nest 约定了 3 种方法名:
foregister 是用于在整个应用程序中注册全局提供者的方法。当我们在应用程序的任何地方都需要访问该提供者时,可以使用 register 来注册。
forRoot 是用于在根模块中注册模块的方法。它将模块中的提供者和导出的模块注册为全局可访问的,这意味着其他模块可以直接使用这些提供者和导出的模块。
forFeature 是用于在特定模块中注册模块的方法。它将模块中的提供者和导出的模块注册为仅在该模块中可访问的。这通常用于在模块内部使用的服务和功能。
并且这些方法都可以写 xxxAsync 版本,也就是传入 useFactory 等 option,内部注册异步 provider。

Nest 还提供了另一种方式来创建动态模块
我们在生成一个新的模块:

nest g module aaa

创建一个controller:

nest g controller aaa --no-spec

新建一个 aaa.module-definition.ts 文件:

import { ConfigurableModuleBuilder } from "@nestjs/common";

/**
 * 定义了AaaModule的配置选项接口。
 * 
 * 该接口包括了aaa和bbb两个属性,分别对应不同的配置需求。
 */
export interface AaaModuleOptions {
    aaa: string;
    bbb: number;
}

/**
 * 使用ConfigurableModuleBuilder构建AaaModule的配置类和选项令牌。
 * 
 * 通过这种方式,可以动态配置模块的选项,并提供了一个令牌用于依赖注入,以便在模块中访问这些配置选项。
 */
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
    new ConfigurableModuleBuilder<AaaModuleOptions>().build()

这段代码是使用NestJS框架定义了一个可配置的模块AaaModule。

  • AaaModuleOptions接口定义了模块的配置选项,包括aaa属性(类型为字符串)和bbb属性(类型为数字)。
  • ConfigurableModuleBuilder是一个NestJS提供的类,用于构建可配置模块。通过调用其build()方法,可以生成一个配置类和一个选项令牌。
  • ConfigurableModuleClass是生成的配置类,可以用于动态配置模块的选项。
  • MODULE_OPTIONS_TOKEN是生成的选项令牌,可以用于依赖注入,在模块中访问配置选项。

然后我们在AaaModule 里继承它

import { Module } from '@nestjs/common';
import { AaaController } from './aaa.controller';
import { ConfigurableModuleClass } from './aaa.module-definition';

@Module({
  controllers: [AaaController]
})
export class AaaModule extends ConfigurableModuleClass {}

这样这个 CccModule 就已经有了 register 和 registerAsync 方法
app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TestModule } from './test/test.module';
import { AaaModule } from './aaa/aaa.module';

@Module({
  imports: [TestModule.register({ test: '666' }),
  AaaModule.register({
    aaa: 'aaa',
    bbb: 1
  }),
  // AaaModule.registerAsync({
  //   useFactory: () => ({
  //     aaa: 'aaa',
  //     bbb: 1
  //   })
  // })
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }

接着我们在 Controller 注入 aaa.controller.ts

import { Controller, Get, Inject } from '@nestjs/common';
import { AaaModuleOptions, MODULE_OPTIONS_TOKEN } from './aaa.module-definition';

@Controller('aaa')
export class AaaController {

    @Inject(MODULE_OPTIONS_TOKEN)
    private options: AaaModuleOptions;

    @Get('')
    hello() {
        return this.options;
    }
}

启动项目

pnpm run start:dev

1717914850954.png
1717914955633.png
可以看到拿到了options 对象 我们可以用来做配置
如果要用 forRoot、forFeature 可以调用 setClassMethodName 函数来设置一下

import { ConfigurableModuleBuilder } from "@nestjs/common";

/**
 * 定义了AaaModule的配置选项接口。
 * 
 * 该接口包括了aaa和bbb两个属性,分别对应不同的配置需求。
 */
export interface AaaModuleOptions {
    aaa: string;
    bbb: number;
}

/**
 * 使用ConfigurableModuleBuilder构建AaaModule的配置类和选项令牌。
 * 
 * 通过这种方式,可以动态配置模块的选项,并提供了一个令牌用于依赖注入,以便在模块中访问这些配置选项。
 */
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
    new ConfigurableModuleBuilder<AaaModuleOptions>().setClassMethodName('forRoot').build()
import { ConfigurableModuleBuilder } from "@nestjs/common";

/**
 * 定义了AaaModule的配置选项接口。
 * 
 * 该接口包括了aaa和bbb两个属性,分别对应不同的配置需求。
 */
export interface AaaModuleOptions {
    aaa: string;
    bbb: number;
}

/**
 * 使用ConfigurableModuleBuilder构建AaaModule的配置类和选项令牌。
 * 
 * 通过这种方式,可以动态配置模块的选项,并提供了一个令牌用于依赖注入,以便在模块中访问这些配置选项。
 */
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
    new ConfigurableModuleBuilder<AaaModuleOptions>().setClassMethodName('forFeature').build()

我们还可以设置为全局模块:
setExtras 第一个参数是给 options 扩展啥 extras 属性,第二个参数是收到 extras 属性之后如何修改模块定义

import { ConfigurableModuleBuilder } from "@nestjs/common";

/**
 * 定义了AaaModule的配置选项接口。
 * 
 * 该接口包括了aaa和bbb两个属性,分别对应不同的配置需求。
 */
export interface AaaModuleOptions {
    aaa: string;
    bbb: number;
}

/**
 * 使用ConfigurableModuleBuilder构建AaaModule的配置类和选项令牌。
 * 
 * 通过这种方式,可以动态配置模块的选项,并提供了一个令牌用于依赖注入,以便在模块中访问这些配置选项。
 */
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
    new ConfigurableModuleBuilder<AaaModuleOptions>()
        .setClassMethodName('register')
        .setExtras({
            isGlobal: true
        }, (definition, extras) => ({
            ...definition,
            global: extras.isGlobal,
        }))
        .build()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/764136.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python酷库之旅-第三方库openpyxl(20)

目录 一、 openpyxl库的由来 1、背景 2、起源 3、发展 4、特点 4-1、支持.xlsx格式 4-2、读写Excel文件 4-3、操作单元格 4-4、创建和修改工作表 4-5、样式设置 4-6、图表和公式 4-7、支持数字和日期格式 二、openpyxl库的优缺点 1、优点 1-1、支持现代Excel格式…

【技术杂谈】如何访问Github | 解决无法连接Github的问题

访问网页的过程 什么是域名&#xff1f;什么是IP地址&#xff1f;- 域名是网站的名称。 - IP地址是服务器在互联网上的逻辑地址。域名往往是固定的&#xff0c;但是IP地址很有可能是会改变的。计算机通过Host文件检查本地缓存是否有域名对应IP地址 Host文件路径 C:\Windows\Sy…

6.The hardest part about learing hard things(学一件难的事,难在哪里)

I’ve been recording a lot of podcast interviews for my upcoming book, Ultralearning.One of the reurring themes I’ve noticed in our conversations is that how people feel about learning is the overwhelming cause of the results they experience. 我为我的新书…

解决VSCode无法用ssh连接远程服务器的问题

原因&#xff1a; 因为windows自带的ssh无法连接远程服务器&#xff0c;需要用git底下的ssh.exe。 搜了很久&#xff0c;试过很多方法&#xff0c;包括替换掉环境变量中的ssh&#xff0c;但是都无效&#xff0c;最后发现是要在VSCode中配置需要使用哪个ssh.exe。 步骤&#…

11.优化算法之栈

1.删除字符串中的所有相邻重复项 可以用数组模拟栈结构 class Solution {public String removeDuplicates(String s) {if(s.length()<1){return s;}StringBuffer retnew StringBuffer();for(int i0;i<s.length();i){if(ret.length()<1){ret.append(s.charAt(i));}els…

字符编码-unicode码表

unicode在线码表&#xff1a;https://www.tamasoft.co.jp/en/general-info/unicode.html Unicode Table

Stable Diffusion中放大图像的3种方法

前言 要执行 ControlNet tile upscale&#xff1a; 您想使用 Stable Diffusion 创建包含大量细节的大型图像吗&#xff1f;您将需要使用升频器。在本文中&#xff0c;您将学习 3 种放大图像的方法。 人工智能升级器标清高档ControlNet瓷砖高档 您将看到比较并了解这些方法的优…

【Arduino】小飞鱼通达二开实验ESP32使用红外寻迹传感器 (图文)

在智能小车项目中都会有一个功能就是自动巡线&#xff0c;今天小飞鱼通达来实验的就是这个红外寻迹传感器。 红外寻迹传感器的原理就是有一个小灯发出红外光&#xff0c;光线照到物体后进行反射&#xff0c;有一个接收器进行接收&#xff0c;当在一定距离内会导通电路&#xf…

【AI绘画Stable Diffusion】教你制作 SD 光影文字,保姆级教程建议收藏!(附模型下载)

大家好&#xff0c;我是设计师阿威 最近光影文字又开始火起来了。今天讲讲怎么利用 Stable Diffusion 的 ControlNet 插件来制作光影图片。 1.下载光影模型组件 1.SD主模型&#xff1a;majicMIX realistic V6、xxmix9realistic_v26 2. ControlNet 的模型&#xff1a;Bright…

3、加密算法-AES和RSA

前两节博客主要是针对MD5和哈希算法&#xff0c;数字签名算法做了阐述和总结&#xff1b; 这篇文章主要是针对AES和RSA做一个概况和比较&#xff0c;以及相关的一些概念&#xff1b; 一、对称加密算法 对称加密算法是指加密和解密采用相同的密钥口&#xff0c;是可逆的(即可解…

高等数学在Android开发中的应用:函数极限与算法优化

高等数学在Android开发中的应用:函数极限与算法优化 在Android开发中,高等数学中的许多概念和技术都能够显著提高应用程序的性能和功能。这篇博客将探讨一些具体的数学原理,特别是函数极限在Android中的实际应用。 函数极限的基本概念 函数极限是微积分的基础,广泛应用于…

R可视化:好看的气泡图

加载R包 library(tidyverse) library(camcorder)gg_record(dir "tidytuesday-temp", device "png", width 8, height 8, units "in", dpi 320)导入数据 team_results <- readr::read_csv(https://raw.githubusercontent.com/rfordata…

有手就行,轻松本地部署 Llama、Qwen 大模型,无需 GPU

用 CPU 也能部署私有化大模型&#xff1f; 对&#xff0c;没错&#xff0c;只要你的电脑有个 8G 内存&#xff0c;你就可以轻松部署 Llama、Gemma、Qwen 等多种开源大模型。 非技术人员&#xff0c;安装 Docker、Docker-compose 很费劲&#xff1f; 不用&#xff0c;这些都不…

vue中路由来回切换页面直接卡死

今天发现一个很严重的问题&#xff0c;项目好不容易做好了&#xff0c;结果页面多了&#xff0c;切换之后卡死。页面所有的交互效果都失效了。 排查了许久的错误原因最后发现原来是路由名称重复了。 如上图当页面跳转到riskdetails详细页面之后&#xff0c;框架则被这个详情页…

SSE代替轮询?

什么是 SSE SSE&#xff08;Server-Sent Events&#xff0c;服务器发送事件&#xff09;&#xff0c;为特定目的而扩展的 HTTP 协议&#xff0c;用于实现服务器向客户端推送实时数据的单向通信。如果连接断开&#xff0c;浏览器会自动重连&#xff0c;传输的数据基于文本格式。…

高温下的稳定选择 —— PP消解管,耐化学更耐用

PP消解管&#xff0c;即聚丙烯材质的消解管&#xff0c;是一种常用于化学分析中的实验室设备&#xff0c;主要用于样品的消解处理。以下是PP消解管的一些主要特性和应用&#xff1a; 主要特性&#xff1a; 1. 耐化学腐蚀&#xff1a;PP材料对多数酸、碱和有机溶剂具有良好的耐…

Vue笔记-vue中使用JS创建的函数

主要是公司对前端要求不高&#xff0c;能解决问题就行了&#xff0c;前端不太熟&#xff0c;用js这种处理起来方便&#xff0c;在此记录下。 在src中创建一个api目录&#xff0c;新建custom.js export const getDivHeightByClass (className) > {let divElements docume…

MySQL数据库中文乱码处理

出现中文乱码之后处理方式 1、执行下面语句查看一下关于编码方式 show variables like %char%结果展示&#xff1a;【你应该和我的不一样】 2、如果你的和我查询结果不一致请设置成一致语句&#xff0c;根据自己需要复制语句 如下&#xff1a;【除了最后一条记录哈】 SET G…

mysql中的递归函数recursive

递归部门 WITH recursive dept_tree AS (SELECTsd.mine_id AS mine_id,sd.dept_id AS dept_id,sd.tenant_id AS tenant_id,sd.order_num,sd.dept_name AS topName,sd.dept_id AS topIdFROMsys_dept sdWHERE<!-- 加上or后也会查询出dept节点 sd.parent_id #{deptId} or sd.…

.net core 的缓存方案

这里主要讲两个缓存的使用&#xff0c;MemoryCache和Redis 先讲讲常见的缓存 1、.net framework web中自带有Cache缓存&#xff0c;这种缓存属于粘性缓存&#xff0c;是缓存到项目中的&#xff0c;项目从服务器迁移的时候缓存的内容也能够随着服务器一起迁移 2、MemoryCache缓存…