Midway-Web中间件

1,383 阅读3分钟

根据文档去学习使用Web中间件

什么是Web中间件

Web 中间件是在控制器调用 之前 和 之后(部分) 调用的函数。 中间件函数可以访问请求和响应对象。

不同的上层 Web 框架中间件形式不同,EggJS 的中间件形式和 Koa 的中间件形式相同,都是基于洋葱圈模型。而 Express 则是传统的队列模型。

Web中间件的作用

对于Midway定义的Web中间件和我使用koa时候的拦截有些类似,可以非常方便的实现后置处理逻辑。

举例说明:

在koa中使用全局拦截判断请求头携带的token是否正确

app.use(async (ctx, next) => {
    let url = ctx.request.url
    list.forEach((item,index)=>{if(item.name === url){ key=index }})
    if(!~key){
        list.push({name:ctx.request.url,count:1});
        if( url === '/login'){
            await next()
        }else{
            let token = ctx.request.header.token||[]
            let user = await tools.search(User,{token},"all")
            if(user.length){
                await next()
            }else{
                ctx.body = {
                    "retCode": false,
                    "resultMsg": '登录已失效请重新登录',
                    "errorCode": 3
                }
            }
        }
    }else{
        if( url === '/login'){
            await next()
        }else{
            let token = ctx.request.header.token||[]
            let user = await tools.search(User,{token},"all")
            if(user.length){
                await next()
            }else{
                ctx.body = {
                    "retCode": false,
                    "resultMsg": '登录已失效请重新登录',
                    "errorCode": 3
                }
            }
        }  
    }
})

Midway的Web中间件用官方例子说明

export class TokenMiddleware implements IWebMiddleware {
  resolve() {
    return async (ctx: Context, next: IMidwayWebNext) => {
      // 控制器前执行的逻辑
      const startTime = Date.now();
      ctx.body = { name:false }
      // 执行下一个 Web 中间件,最后执行到控制器
      // await next();
      // 控制器之后执行的逻辑
      console.log(Date.now() - startTime);
    };
  }
}

如上所示await next() 控制是否执行控制器,光从使用上看就是Generator 函数的封装,yield 包含着控制器,这里逻辑判断可以直接使用koa的,但是后面的next不能再去执行了。

注:TokenMiddleware在使用时首字母小写驼峰命名具体原因如下

key属性说明

服务

使用服务的过程分为几部分:

  • 1、使用 @Provide 装饰器暴露你的服务

  • 2、在调用的代码处,使用 @Inject 装饰器注入你的服务

  • 3、调用注入服务,执行对应的方法

Midway 的核心 “依赖注入” 容器会自动关联你的控制器(Controller) 和服务(Service),在运行过程中会自动初始化所有的代码,你无需手动初始化这些 Class

注入行为描述

Provide 装饰器的作用:

  • 1、这个 Class,被依赖注入容器托管,会自动被实例化(new)
  • 2、这个 Class,可以被其他在容器中的 Class 注入

而对应的 @Inject 装饰器,作用为:

  • 1、在依赖注入容器中,找到对应的属性名,并赋值为对应的实例化对象 @Provide 和 @Inject 装饰器是有参数的,并且他们是成对出现。

这个参数叫做 依赖注入标识符,这里先用 key 代替。
这里就涉及到了Midwayde默认行为了。
默认情况下:

  • 1、 @Provide 取 类名的驼峰字符串 作为 key

  • 2、 @Inject 根据 规则 获取 key 规则如下:

  • 1、如果装饰器包含参数,则以 参数字符串 作为 key

  • 2、如果没有参数,标注的 TS 类型为 Class,则将类 @Provide 的 key 作为 key

  • 3、如果没有参数,标注的 TS 类型为非 Class,则将 属性名 作为 key

两者相互一致即可关联。

export interface IService { }
// service
@Provide()  //  这里暴露的 key 是userServiceexport
// 也可以自定义key @Provide('testService')但是@Inject中需要对应
class UserService implements IService {
    //...
}
// controller 
@Provide()
@Controller('/api/user')
export class APIController {

@Inject('userService')
// 对应@Provide @Inject('testService')
userService1: UserService;// 这里注入的 key 是 userService

@Inject()
userService2: UserService;

@Inject()
userService: IService;
}

总结

// middleware
export class TokenMiddleware implements IWebMiddleware {
  resolve() {
    return async (ctx: Context, next: IMidwayWebNext) => {
      // 控制器前执行的逻辑
      const startTime = Date.now();
      ctx.body = { name:false }
      // 执行下一个 Web 中间件,最后执行到控制器
      // await next();
      // 控制器之后执行的逻辑
      console.log(Date.now() - startTime);
    };
  }
}
// 使用时
@Get('/', { middleware: [ 'tokenMiddleware' ]})
async home() {}