通过反射获取Request和Response(14)

95 阅读2分钟

源码: j-spring-eco ts版本的Spring全家桶

前言

熟悉springWeb的都知道,参数反射。

  @Get()
  @ApiRemark('测试反射')
  async testQuery3(
    @RequestParam('a') a: number,
    @RequestParam('ids') ids: ArrayNumber,
    @Param() req: Request,
    @Param() res: Response,
    @Param() session: Session
  ) {
    return {};
  }

语言层面,相比较java版本的,ts确实要稍微麻烦了一点。例如@RequestParam 需要手动输入参数名,req: Request需要添加注解。且Request必须是一个类(函数)。

整体还能接受,不算特别麻烦。带来的便利性也是不言而喻的。相比express的router明显更加直观和便捷,顺便还做了一次参数检查。

麻烦点

express 4.x是js编写的,随之tds文件肯定是手动编写的了。描述文件里面的Request和Response是一个接口,这是无法用于加在参数后面作为反射类型的,因为接口在编译的时候就清除了。

如果在项目里面实现Request和Response接口,即使有自动生成接口的模板代码,但是依旧非常的麻烦。将近一千行,还得一行行改,还有包的依赖问题,瞬间没有心情了。

解决办法

1、创建一个包

创建一个j-spring-type-wrap项目,就是用j-spring-cli创建一个模板项目

2、创建一些简单的实现类 index.ts

```js  
//这些类本身没有意义,只是为了参数反射使用。只需要类名就行了
//添加Abs后缀是放置和自动生成的tds代码起冲突
export class RequestAbs {}
export class ResponseAbs {}
export class ExpressServerAbs {}
export class ExpressAppAbs {}
```

3、手动实现 index.tds

import {
  Request,
  MediaType,
  ParamsDictionary,
  Response,
  NextFunction,
  CookieOptions,
  Errback,
  Application,
  RequestParamHandler,
  Send,
} from 'express-serve-static-core';
export class RequestAbs implements Request {
    // vs-code会自动把Request的接口实现。不需要额外编辑。
}
  • 代码太长了接近上千行,好在都是自动生成的。
  • 这个包就完成了,发布就完事了。

项目里面使用

  • 导出类
import {
  RequestAbs as Request,
  ResponseAbs as Response,
  ExpressAppAbs as ExpressApp,
  ExpressServerAbs as ExpressServer,
} from 'j-spring-type-wrap';

export { Request, Response, ExpressApp, ExpressServer };
  • 添加参数拦截器
class ParamInteceptor implements SpringWebParamInteceptor<any> {
  error(_bean: any): void {}
  success(_bean: any): void {}
  isSpringWebParamInteceptor(): boolean {
    return true;
  }
  getAnnotation(): Function {
    return Param;
  }
  getBean(req: Request, res: Response, pa: Anntation) {
    const { reflectType } = pa.params as ReflectParam;
    if (reflectType === Request) return req;
    if (reflectType === Response) return res;
    if (reflectType === Session) {
      if (req.session === void 0) {
        throw '没有安装session插件';
      }
      return new Session(req.session);
    }
    throw `不支持参数反射类型: [${reflectType}]`;
  }
}