扩展配置类
针对各种扩展的情况,我们提供了通用的高级能力,目前是通过固定的 src/configuration.ts 文件来实现的,此文件为特殊规范,目前无法改变文件名。
例如:
base-app├── package.json└── src├── configuration.ts└── lib└── userManager.ts
此文件为一个特殊类,类名随意,通过 @Configuration 修饰。
// src/configuration.tsimport { Configuration } from '@midwayjs/decorator';@Configuration({imports: [],importObjects: []})export class ContainerLifeCycle {}
@Configuration 的能力非常多,提供了扩展 IoC 容器的能力,该文件也是后期扩展容器生命周期的核心文件。
函数配置
当代码逻辑变多的时候,特别是跨环境时,我们就需要传统的配置能力。
我们可以针对不同环境创建配置文件,文件内容为 JSON 格式,目录结构如下。
base-app├── package.json└── src├── configuration.ts└── config└── config.default.ts
我们需要在 configuration.ts 中配置需要依赖的环境文件。
- 1、文件以相对路径存在,目录结构随意自定,推荐传统的
config/ - 2、文件指定无需 ts 后缀
- 3、目前配置文件必须指定添加
- 4、合并规则,在
NODE_ENV=**环境下,会加载**/config.defaut.ts的文件以及**/config.{env}.ts文件。
比如,下面代码在本地会加载 config.default.* 和 config.local.* 文件,但是如果在其他环境,只会加载 config.default.* 。
:::info
importConfigs 这里只是指定需要加载的文件,实际运行时会自动选择当前的环境来找对应的文件后缀。
:::
可以指定加载一个目录,目录里所有的 config.*.ts 都会被扫描加载。
// src/configuration.tsimport { Configuration } from '@midwayjs/decorator';@Configuration({importConfigs: ['./config/',]})export class ContainerLifeCycle {}
或者手动指定一批文件。
// src/configuration.tsimport { Configuration } from '@midwayjs/decorator';@Configuration({importConfigs: ['./config/config.default','./config/config.local']})export class ContainerLifeCycle {}
配置格式
配置文件格式基本为 json,也可以通过函数返回,编写逻辑。
比如:
// config.default.tsexport = {userService: {appname: 'test'}};
或者支持回调方式。
// config.default.tsexport = () => {return {userService: {appname: 'test'},};};
可以使用 @Config 装饰器注入。
import { Config } from '@midwayjs/decorator';export class IndexHandler {@Config('userService')userConfig;async handler() {console.log(this.userConfig.appname); // test}}
配置加载顺序
配置存在优先级(应用代码 > 框架 > 扩展),相对于此运行环境的优先级会更高。
比如在 prod 环境加载一个配置的加载顺序如下,后加载的会覆盖前面的同名配置。
-> 扩展 config.default.ts-> 框架 config.default.ts-> 应用 config.default.ts-> 扩展 config.prod.ts-> 框架 config.prod.ts-> 应用 config.prod.ts
配置生命周期
在通常情况下,我们希望在应用启动的时候做一些初始化、或者其他一些预处理的事情,比如创建数据库连接、预生成一些配置,而不是在请求响应时去处理。
通过 src/configuration.ts 文件,导出的类实现 ILifeCycle 接口,就可以在应用 ready 的时候处理这类需求。
接口定义如下。
interface ILifeCycle {/*** 在应用 ready 的时候执行* @param container IoC 容器*/onReady(container?: IMidwayContainer): Promise<void>;/*** 在应用停止的时候执行* @param container IoC 容器*/onStop?(container?: IMidwayContainer): Promise<void>;}
举个例子。
我们需要在初始化时提前连接一个数据库,由于在类中,所以也可以通过 @Inject 装饰器注入 db 这样一个数据库的连接工具类,这个实例包含 connect 和 close 两个函数:
@Configuration({// 一些配置,见 Configuration 说明imports: ['../../midway-plugin-mock/src','../../midway-plugin-ok/src'],importObjects: {aa: 123}})class ContainerConfiguration implements ILifeCycle {@Inject()db: any;async onReady(container: IMidwayContainer): Promise<void> {// 建立数据库连接await this.db.connect();}async onStop(): Promise<void> {// 关闭数据库连接await this.db.close();}}
这样,我们就能够在应用启动时建立数据库连接,而不是在请求响应时再去创建。同时,在应用停止时,也可以优雅的关闭数据库连接。
除此之外,通过这个方式,可以对默认注入的对象做扩充。
import * as sequelize from 'sequelize';@Configuration()class ContainerConfiguration implements ILifeCycle {async onReady(container: IMidwayContainer): Promise<void> {// 三方包对象container.registerObject('sequelize', sequelize);}}
在其他的类中可以直接注入使用。
export class IndexHandler {@Inject()sequelize;async handler() {console.log(this.sequelize);}}
