NestJS中使用DynamicModule构建插件系统

news/2024/12/25 0:39:16/

1. 介绍

在NestJS中,模块是组织代码的基本单元,它将相关的服务和控制器组织在一起。然而,在某些情况下,我们可能需要根据不同的条件动态加载模块,以满足不同的业务需求。这时,就可以使用DynamicModule了。

DynamicModule是NestJS提供的一种动态加载模块的方式,它允许我们在运行时动态地加载模块,下面就看看怎样通过DynamicModule构建插件系统。下面例子

  1. 创建了一个插件文件,其中定义了一些方法,用于动态加载;
  2. 创建了一个插件加载模块,用来加载上面的插件文件;
  3. 在主模块中,动态加载插件模块;
  4. 在主模块的controller中使用插件加载模块加载插件,并调用插件方法。

2. 创建插件文件

/tmp/test.js

module.exports = {helloworld: function () {console.log('load from dynamically loaded module!');return 'Hello World';},hello: function (name) {console.log('load from dynamically loaded module!');return 'Hello ' + name;},
};

3. 创建插件加载服务类

plugin-loader.service.ts

import { Inject, Injectable } from '@nestjs/common';
import * as path from 'path';
import * as vm from 'vm';
import * as fs from 'fs';@Injectable()
export class PluginLoaderService {constructor(@Inject('PLUGIN_FILE') private readonly pluginFile: string) {}async loadPlugin(): Promise<any> {console.log('load plugin ...', path.resolve(this.pluginFile));const content = fs.readFileSync(path.resolve(this.pluginFile)).toString();const sandbox = {module: { exports: {} },console: console,};vm.createContext(sandbox);const script = new vm.Script(content, { filename: 'plugin-module.js' });script.runInContext(sandbox);return sandbox.module.exports;}
}
  • PluginLoaderService 用来根据传入的插件文件路径,使用vm加载之。

4. 创建插件加载模块

plugin.module.ts

import { DynamicModule, Module } from '@nestjs/common';
import { PluginLoaderService } from './plugin-loader.service';@Module({})
export class PluginModule {static loadPlugin(file: string): DynamicModule {return {module: PluginModule,providers: [{provide: 'PLUGIN_FILE',useValue: file,},PluginLoaderService,],exports: [PluginLoaderService],};}
}
  • PluginModule 用来加载插件文件,并返回一个DynamicModule,其中包含PluginLoaderService。
  • 在主模块中,可以通过调用PluginModule.loadPlugin(file)来动态加载插件文件。

5. 在主模块中使用插件加载模块

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PluginModule } from './plugins/plugin.module';import * as path from 'path';@Module({imports: [PluginModule.loadPlugin('/tmp/test.js'),],controllers: [AppController],providers: [AppService],
})
export class AppModule {}
  • 在主模块中,通过调用PluginModule.loadPlugin(file)来动态加载插件文件,并将其作为模块导入。

6. 在控制器中使用插件

app.controller.ts

import { Controller, Get, Inject } from '@nestjs/common';
import { AppService } from './app.service';
import { PluginLoaderService } from './plugins/plugin-loader.service';@Controller()
export class AppController {constructor(private readonly appService: AppService,private readonly pluginLoaderService: PluginLoaderService,) {}@Get()async getHello() {const plugin = await this.pluginLoaderService.loadPlugin();console.log(plugin.helloworld());console.log(plugin.hello('kongxx'));return this.appService.getHello();}
}
  • 在控制器中,通过调用PluginLoaderService.loadPlugin()来加载插件,并调用插件的方法。

http://www.ppmy.cn/news/1557864.html

相关文章

若依微服务如何获取用户登录信息

文章目录 1、需求提出2、应用场景3、解决思路4、注意事项5、完整代码第一步&#xff1a;后端获取当前用户信息第二步&#xff1a;前端获取当前用户信息 5、运行结果6、总结 1、需求提出 在微服务架构中&#xff0c;获取当前用户的登录信息是开发常见的需求。无论是后端处理业务…

whisper实时语音转文字

import whisperimport osdef check_file_exists(file_path):if not os.path.exists(file_path):raise FileNotFoundError(f"音频文件不存在: {file_path}")# 音频文件路径 audio_path r"D:\视频\temp_audio.wav"# 检查文件是否存在 check_file_exists(aud…

力扣238. 除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…

Qt创建自定义Help文档步骤

Qt创建自定义Help文档步骤 上一篇文章中,介绍了Qt提供的Help框架创建帮助文档,这一篇实际来演示一下创建的步骤。 一、创建Qt项目 比如Qt创建了一个项目,我在菜单栏预留了一个接口,点击进入帮助模块,如下图所示: 当我点击菜单栏中的“帮助”时,帮助模块就弹出。 二、…

搭建Docker Harbor仓库

搭建 Docker Harbor 仓库是一个常见的任务&#xff0c;Harbor 是一个企业级的 Docker Registry 管理工具&#xff0c;提供了镜像管理、用户权限控制、镜像扫描等功能。下面是搭建 Harbor 仓库的详细步骤。 1. 环境准备 在开始之前&#xff0c;确保你的服务器满足以下要求&…

Maven 中央仓库访问过慢的解决方案--设置国内镜像

在现今的 Java 开发活动中, 无论你是用古老的 Ant, 还是 Maven 本身, 亦或是 Gradle, 你都经常需要访问 Maven 的中央仓库以获取所依赖的包. 鉴于中央仓库的访问巨大, 再背上我们特殊国情的友军火力的锅, 获取依赖的过程中经常慢得令人发指, 甚至导致构建失败, IDE 失去响应等等…

MySQL使用LOAD DATA INFILE方式导入文本文件

【图书推荐】《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;》-CSDN博客 《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…

在 Go 中利用 ffmpeg 进行视频和音频处理

在 Go 中利用 ffmpeg 进行视频和音频处理 ffmpegutil 包概述主要功能介绍1. 视频格式转换2. 提取音频3. 获取视频信息4. 创建视频缩略图5. 提取随机帧无线程版本&#xff1a;多线程版本&#xff1a; 总结 ffmpeg 是一款功能强大的多媒体处理工具&#xff0c;支持视频和音频的编…