最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

NodeJS仿WebApi路由示例

 更新時間:2017年02月28日 16:54:00   作者:布魯克石  
本篇文章主要介紹了NodeJS仿WebApi路由示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

用過WebApi或Asp.net MVC的都知道微軟的路由設計得非常好,十分方便,也十分靈活。雖然個人看來是有的太靈活了,team內(nèi)的不同開發(fā)很容易使用不同的路由方式而顯得有點混亂。 不過這不是重點,我在做Node項目的時候就覺得不停的用use(...)來指定路由路徑很煩人,所以用Typescript寫了這個基于KoaKoa-router的路由插件,可以簡單實現(xiàn)一些類似WebApi的路由功能。

目標是和WebApi一樣:

1.加入的controller會自動加入路由。

2.也可以通過path()手動指定路由。

3.可以定義http method, 如GETPOST等。

4.Api的參數(shù)可以指定url里的query param、path param以及body等。

包已經(jīng)上傳到npm中,npm install webapi-router 安裝,可以先看看效果:

第一步,先設置controllers的目錄和url的固定前綴

所有的controller都在這目錄下,這樣會根據(jù)物理路徑自動算出路由。 url的固定前綴就是host和路由之間的,比如localhost/api/v2/user/name,api/v2就是這個固定前綴。

import { WebApiRouter } from 'webapi-router';

app.use(new WebApiRouter().router('sample/controllers', 'api'));

第二步是controller都繼承自BaseController

export class TestController extends BaseController
{

}

第三步給controller的方法加上裝飾器

@POST('/user/:name')
postWithPathParam(@PathParam('name') name: string, @QueryParam('id') id: string, @BodyParam body: any) {
  console.info(`TestController - post with name: ${name}, body: ${JSON.stringify(body)}`);
  return 'ok';
}

@POST里的參數(shù)是可選的,空的話會用這個controller的物理路徑做為路由地址。

:name是路徑里的變量,比如 /user/brook, :name就是brook,可以在方法的參數(shù)里用@PathParam得到

@QueryParam可以得到url?后的參數(shù)

@BodyParam可以得到Post上來的body

是不是有點WebApi的意思了。

現(xiàn)在具體看看是怎么實現(xiàn)的

實現(xiàn)過程其實很簡單,從上面的目標入手,首先得到controllers的物理路徑,然后還要得到被裝飾器裝飾的方法以及它的參數(shù)。
裝飾器的目的在于要得到是Get還是Post等,還有就是指定的Path,最后就是把node request里的數(shù)據(jù)賦值給方法的參數(shù)。

核心代碼:

得到物理路徑

initRouterForControllers() {
  //找出指定目錄下的所有繼承自BaseController的.js文件
  let files = FileUtil.getFiles(this.controllerFolder);

  files.forEach(file => {
    let exportClass = require(file).default;

    if(this.isAvalidController(exportClass)){
      this.setRouterForClass(exportClass, file);
    }
  });
}

從物理路徑轉(zhuǎn)成路由

private buildControllerRouter(file: string){

  let relativeFile = Path.relative(Path.join(FileUtil.getApiDir(), this.controllerFolder), file);
  let controllerPath = '/' + relativeFile.replace(/\\/g, '/').replace('.js','').toLowerCase();

  if(controllerPath.endsWith('controller'))
    controllerPath = controllerPath.substring(0, controllerPath.length - 10);

  return controllerPath;
}

裝飾器的實現(xiàn)

裝飾器需要引入reflect-metadata庫

先看看方法的裝飾器,@GET,@POST之類的,實現(xiàn)方法是給裝飾的方法加一個屬性Router,Router是個Symbol,確保唯一。 然后分析裝飾的功能存到這個屬性中,比如Method,Path等。

export function GET(path?: string) {
  return (target: BaseController, name: string) => setMethodDecorator(target, name, 'GET', path);
} 

function setMethodDecorator(target: BaseController, name: string, method: string, path?: string){
  target[Router] = target[Router] || {};
  target[Router][name] = target[Router][name] || {};
  target[Router][name].method = method;
  target[Router][name].path = path;
}

另外還有參數(shù)裝飾器,用來給參數(shù)賦上request里的值,如body,param等。

export function BodyParam(target: BaseController, name: string, index: number) {
  setParamDecorator(target, name, index, { name: "", type: ParamType.Body });
}

function setParamDecorator(target: BaseController, name: string, index: number, value: {name: string, type: ParamType}) {
  let paramTypes = Reflect.getMetadata("design:paramtypes", target, name);
  target[Router] = target[Router] || {};
  target[Router][name] = target[Router][name] || {};
  target[Router][name].params = target[Router][name].params || [];
  target[Router][name].params[index] = { type: paramTypes[index], name: value.name, paramType: value.type };
}

這樣裝飾的數(shù)據(jù)就存到對象的Router屬性上,后面構(gòu)建路由時就可以用了。

綁定路由到Koa-router

上面從物理路徑得到了路由,但是是以裝飾里的參數(shù)路徑優(yōu)先,所以先看看剛在存在原型里的Router屬性里有沒有Path,有的話就用這個作為路由,沒有Path就用物理路由。

private setRouterForClass(exportClass: any, file: string) { 

  let controllerRouterPath = this.buildControllerRouter(file);
  let controller = new exportClass();

  for(let funcName in exportClass.prototype[Router]){
    let method = exportClass.prototype[Router][funcName].method.toLowerCase();
    let path = exportClass.prototype[Router][funcName].path;

    this.setRouterForFunction(method, controller, funcName, path ? `/${this.urlPrefix}${path}` : `/${this.urlPrefix}${controllerRouterPath}/${funcName}`);
  }
}

給controller里的方法參數(shù)賦上值并綁定路由到KoaRouter

private setRouterForFunction(method: string, controller: any, funcName: string, routerPath: string){
  this.koaRouter[method](routerPath, async (ctx, next) => { await this.execApi(ctx, next, controller, funcName) });
}

private async execApi(ctx: Koa.Context, next: Function, controller: any, funcName: string) : Promise<void> { //這里就是執(zhí)行controller的api方法了
  try
  {
    ctx.body = await controller[funcName](...this.buildFuncParams(ctx, controller, controller[funcName]));
  }
  catch(err)
  {
    console.error(err);
    next(); 
  }
}

private buildFuncParams(ctx: any, controller: any, func: Function) { //把參數(shù)具體的值收集起來
  let paramsInfo = controller[Router][func.name].params;
  let params = [];
  if(paramsInfo)
  {
    for(let i = 0; i < paramsInfo.length; i++) {
      if(paramsInfo[i]){
        params.push(paramsInfo[i].type(this.getParam(ctx, paramsInfo[i].paramType, paramsInfo[i].name)));
      } else {
        params.push(ctx);
      }
    }
  }
  return params;
}

private getParam(ctx: any, paramType: ParamType, name: string){ // 從ctx里把需要的參數(shù)拿出來
  switch(paramType){
    case ParamType.Query:
      return ctx.query[name];
    case ParamType.Path:
      return ctx.params[name];
    case ParamType.Body:
      return ctx.request.body;
    default:
      console.error('does not support this param type');
  }
}

這樣就完成了簡單版的類似WebApi的路由.

源碼下載webapi-router_jb51.rar

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 基于Node.js搭建hexo博客過程詳解

    基于Node.js搭建hexo博客過程詳解

    這篇文章主要介紹了基于Node.js搭建hexo博客過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,
    2019-06-06
  • 在Node.js應用程序中處理大數(shù)的操作指南

    在Node.js應用程序中處理大數(shù)的操作指南

    在JavaScript生態(tài)系統(tǒng)中,你可以使用BigInt來處理大整數(shù),但是,你也可以使用具有類似于BigInt功能的第三方庫,本文將是使用BigInt和提供類似功能的流行庫管理大數(shù)的完整指南,我們還將比較第三方庫的用例、優(yōu)勢和劣勢
    2023-06-06
  • nodejs實現(xiàn)一個word文檔解析器思路詳解

    nodejs實現(xiàn)一個word文檔解析器思路詳解

    這篇文章主要介紹了nodejs實現(xiàn)一個word文檔解析器的思路詳解,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-08-08
  • 解決koa2 ctx.render is not a function報錯問題

    解決koa2 ctx.render is not a function報錯問題

    這篇文章主要介紹了解決koa2 ctx.render is not a function報錯問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • npm?install?XXX安裝路徑文件夾權(quán)限問題的解決過程

    npm?install?XXX安裝路徑文件夾權(quán)限問題的解決過程

    這篇文章主要給大家介紹了關(guān)于npm?install?XXX安裝路徑文件夾權(quán)限問題(npm?ERR!?The?operation?was?rejected?by?your?operating?system.errno?-4080)的解決過程,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2023-04-04
  • 在Node.js中實現(xiàn)獲取用戶頻道信息的功能

    在Node.js中實現(xiàn)獲取用戶頻道信息的功能

    在構(gòu)建社交或視頻分享平臺時,允許用戶查看其他用戶的頻道信息是一個基本需求,本文將介紹如何在Node.js應用中,使用Express框架和Mongoose庫來實現(xiàn)這一功能,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下
    2024-04-04
  • Node.js中MongoDB更新數(shù)據(jù)的兩種方法

    Node.js中MongoDB更新數(shù)據(jù)的兩種方法

    本文主要介紹了Node.js中MongoDB更新數(shù)據(jù)的兩種方法,主要包括使用原生的 MongoDB 驅(qū)動程序或者使用 Mongoose 來更新 MongoDB 數(shù)據(jù),
    2023-12-12
  • node.js中的fs.mkdir方法使用說明

    node.js中的fs.mkdir方法使用說明

    這篇文章主要介紹了node.js中的fs.mkdir方法使用說明,本文介紹了fs.mkdir方法說明、語法、接收參數(shù)、使用實例和實現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • 給nodejs升級的兩種方法

    給nodejs升級的兩種方法

    nodejs是一種流行的服務器端JavaScript運行環(huán)境,它經(jīng)常需要更新以獲取最新的功能和性能優(yōu)化,本文將給大家介紹了給nodejs升級的兩種方法,文中通過代碼示例講解非常詳細,需要的朋友可以參考下
    2023-12-12
  • nodejs socket實現(xiàn)的服務端和客戶端功能示例

    nodejs socket實現(xiàn)的服務端和客戶端功能示例

    這篇文章主要介紹了nodejs socket實現(xiàn)的服務端和客戶端功能,結(jié)合具體實例形式分析了nodejs基于socket通信實現(xiàn)的服務端與客戶端功能相關(guān)操作技巧,需要的朋友可以參考下
    2017-06-06

最新評論

剑阁县| 通榆县| 丘北县| 西峡县| 昌邑市| 万山特区| 兴义市| 搜索| 蕉岭县| 临邑县| 天镇县| 新巴尔虎左旗| 石嘴山市| 花莲县| 上饶市| 永靖县| 临泉县| 婺源县| 合肥市| 安远县| 安庆市| 扶余县| 宁德市| 阿城市| 吐鲁番市| 北碚区| 隆子县| 米脂县| 株洲县| 易门县| 阿图什市| 吉木萨尔县| 长丰县| 漾濞| 库车县| 永城市| 工布江达县| 乐亭县| 龙口市| 衡水市| 北流市|