VonaJS AOP编程:全局中间件全攻略

在VonaJS框架中,AOP编程包括三方面:控制器切面内部切面外部切面控制器切面包括五能力:MiddlewareGuardInterceptorPipeFilter

其中,Middleware又分为:局部中间件全局中间件系统中间件。其时序图如下所示:

由图可知,系统中间件在路由匹配之前执行,局部中间件全局中间件在路由匹配之后执行。

为了简化起见,这里仅介绍全局中间件的用法,局部中间件系统中间件的用法,请参见官方文档。

创建中间件

比如,在模块 demo-student 中创建一个 全局中间件: logger

1. Cli命令

bash 复制代码
$ vona :create:bean middleware logger --module=demo-student --boilerplate=cli/middlewareGlobal/boilerplate

2. 菜单命令

bash 复制代码
右键菜单 - [模块路径]: `Vona Aspect/Middleware Global`

中间件定义

typescript 复制代码
export interface IMiddlewareOptionsLogger extends IDecoratorMiddlewareOptionsGlobal {}

@Middleware<IMiddlewareOptionsLogger>({ global: true })
export class MiddlewareLogger extends BeanBase implements IMiddlewareExecute {
  async execute(_options: IMiddlewareOptionsLogger, next: Next) {
    const timeBegin = Date.now();
    const res = await next();
    const timeEnd = Date.now();
    console.log('time: ', timeEnd - timeBegin);
    return res;
  }
}
  • IMiddlewareOptionsLogger: 定义中间件参数
  • execute: 输出执行时长

使用中间件

与局部中间件不同,系统会自动加载全局中间件,并使其生效

中间件参数

可以为中间件定义参数,通过参数更灵活的配置中间件逻辑

比如,为 logger 中间件定义prefix参数,用于控制输出格式

1. 定义参数类型

diff 复制代码
export interface IMiddlewareOptionsLogger extends IDecoratorMiddlewareOptionsGlobal {
+ prefix: string;
}

2. 提供参数缺省值

diff 复制代码
@Middleware<IMiddlewareOptionsLogger>({
  global: true,
+ prefix: 'time',
})

3. 使用参数

diff 复制代码
export interface IMiddlewareOptionsLogger extends IDecoratorMiddlewareOptionsGlobal {
  prefix: string;
}

@Middleware<IMiddlewareOptionsLogger>({
  global: true,
  prefix: 'time',
})
class MiddlewareLogger {
  async execute(options: IMiddlewareOptionsLogger, next: Next) {
    const timeBegin = Date.now();
    const res = await next();
    const timeEnd = Date.now();
-   console.log('time: ', timeEnd - timeBegin);
+   console.log(`${options.prefix}: `, timeEnd - timeBegin);
    return res;
  }
}

4. 使用时指定参数

可以针对某个 API 单独指定全局中间件的参数

diff 复制代码
+ import { Aspect } from 'vona-module-a-aspect';

class ControllerStudent {
  @Web.get()
+ @Aspect.middlewareGlobal('demo-student:logger', { prefix: 'elapsed' })
  async findMany() {}
}
  • 在使用中间件时直接提供参数值即可

5. App config配置

可以在 App config 中配置中间件参数

src/backend/config/config/config.ts

typescript 复制代码
// onions
config.onions = {
  middleware: {
    'demo-student:logger': {
      prefix: 'elapsed',
    },
  },
};

6. 参数优先级

使用时指定参数 > App config配置 > 参数缺省值

中间件顺序

由于全局中间件是默认加载并生效的,所以,VonaJS 提供了两个参数,用于控制中间件的加载顺序

1. dependencies

比如,系统有一个内置全局中间件a-core:gate,我们希望加载顺序如下:a-core:gate > Current

diff 复制代码
@Middleware({
  global: true,
+ dependencies: 'a-core:gate',
  prefix: 'time',
})
class MiddlewareLogger {}

2. dependents

dependents的顺序刚好与dependencies相反,我们希望加载顺序如下:Current > a-core:gate

diff 复制代码
@Middleware({
  global: true,
+ dependents: 'a-core:gate',
  prefix: 'time',
})
class MiddlewareLogger {}

中间件启用/禁用

可以针对某些 API 控制全局中间件的启用/禁用

1. Enable

  • 针对某个 API 禁用
diff 复制代码
class ControllerStudent {
  @Web.get()
+ @Aspect.middlewareGlobal('demo-student:logger', { enable: false })
  async findMany() {}
}
  • 针对所有 API 禁用

src/backend/config/config/config.ts

diff 复制代码
// onions
config.onions = {
  middleware: {
    'demo-student:logger': {
+     enable: false,
    },
  },
};

2. Meta

可以让全局中间件在指定的运行环境生效

名称 类型 说明
flavor string|string[] 参见: 运行环境与Flavor
mode string|string[] 参见: 运行环境与Flavor
instanceName string|string[] 参见: 多实例/多租户
host string|string[] 主机名
  • 举例
diff 复制代码
@Middleware({
  global: true,
+ meta: {
+   flavor: 'normal',
+   mode: 'dev',
+   instanceName: '',
+   host: 'localhost:7102',
+ },
})
class MiddlewareLogger {}

3. match/ignore

可以针对指定的 API 启用/禁用全局中间件

名称 类型 说明
match string|regexp|(string|regexp)[] 针对哪些API启用
ignore string|regexp|(string|regexp)[] 针对哪些API禁用

查看当前生效的全局中间件清单

可以直接在 Controller action 中输出当前生效的全局中间件清单

diff 复制代码
class ControllerStudent {
  @Web.get()
  async findMany() {
+   this.bean.onion.middleware.inspect();
  }
}
  • this.bean.onion: 取得全局 Service 实例 onion
  • .middleware: 取得与中间件相关的 Service 实例
  • .inspect: 输出当前生效的全局中间件清单

当访问findMany API 时,会自动在控制台输出当前生效的全局中间件清单,效果如下:

资源

相关推荐
行走的陀螺仪11 小时前
前端基建从0到1搭建步骤清单(含工具选型+配置要点+落地注意事项)
前端·javascript·typescript·设计规范·前端工程化·规范化·前端基建
ttod_qzstudio14 小时前
Vue 3 的魔法:用 v-bind() 让 CSS 爱上 TypeScript 常量
css·vue.js·typescript
[seven]1 天前
React Router TypeScript 路由详解:嵌套路由与导航钩子进阶指南
前端·react.js·typescript
_Kayo_1 天前
TypeScript 学习笔记2
前端·javascript·typescript
[seven]2 天前
React Router TypeScript 路由详解:类型安全的路由配置与参数处理
安全·react.js·typescript
李子烨2 天前
吃饱了撑的突发奇想:TypeScript 类型能不能作为跑业务逻辑的依据?(纯娱乐)
前端·typescript
坐公交也用券2 天前
适用于vue3+pnpm项目自动化类型检查及构建的Python脚本
开发语言·javascript·python·typescript·自动化
LYFlied2 天前
TypeScript 常见面试问题
ubuntu·面试·typescript
前端不太难2 天前
RN + TypeScript 项目越写越乱?如何规范架构?
前端·javascript·typescript
JQ_Zhang3 天前
极致体验!一个小工具实现智能关键词高亮 (中英文混排/全字匹配)
typescript