ホームページ  >  記事  >  ウェブフロントエンド  >  ノードのバックエンドルーティングの自動読み込みについて説明する記事

ノードのバックエンドルーティングの自動読み込みについて説明する記事

青灯夜游
青灯夜游転載
2023-01-18 20:57:251582ブラウズ

ノードのバックエンドルーティングの自動読み込みについて説明する記事

この記事は、特定の基礎を備えた Node.js 開発者向けの記事です。

難易度

バックグラウンド

今日はノード バックエンドのルーティングの問題について話しましょう。 [関連チュートリアルの推奨事項: nodejs ビデオ チュートリアル

]

フロントエンドの学生または Nodejs サーバーの学生の皆さん、Express と koajs を使用してインターフェイスを作成する場合、ルートを作成する必要はありません。たとえば次のようになります。

ログインインターフェース

router.post('/user/login', user.login);

ユーザー情報の取得インターフェースrouter.get ('/user/info', checkAuth, user.xxx);

この書き方は非常に一般的で、最初にルートを登録し、後で実行するミドルウェアのメソッドを指定します。

しかし、インターフェイスが増えていくと、たとえばインターフェイスが 1,000 個になると、このように 1,000 回登録する必要があり、インターフェイスの数が増えると、非常に面倒で面倒なことになると思います。

##koa&express ルーティングの登録例

const express = require('express');
const router = express.Router();
const user = require('../../controllers/user');
const tokenCheck = require('../../middleware/token_check_api');

//用户注册
router.post('/user/register', user.register);
//用户登录
router.post('/user/login', user.login);
router.post('xxx', tokenCheck, user.xxx);
...假装还有有1000个

1,000 個のインターフェイスを記述する場合、router.js に 1,000 回登録する必要がありますか?

eggjs ルート登録例

'use strict';

// egg-router extends koa-router

import { Application } from 'egg';

export default (app: Application) => {
  const { router, controller, middleware } = app;
  router.get('/', middleware.special(), controller.home.index);
  router.get('/1', middleware.special(), controller.home.index1);
  ....
  router.get('/error', controller.home.error);
};
**この種のプロジェクトが拡大すると、この構成は非常に冗長に見えると思うので、ルートの自動読み込み機構を実装する必要があります。それを改善し、最適化するためです。

1. 効率の向上

2. よりエレガントな記述

共通ルートの自動読み込み

問い合わせてみたところ、いくつかのフレームワークは、さまざまな方法でルートの自動読み込みを実装しています。

1. think シリーズ

最初のシリーズは thinkPHP と thinkjs、参考リンクthinkjs.org/zh-cn/doc /3…

この 2 つの関係は、thinkjs が thinkPHP の考え方に従って設計、開発されたということです。 他の 2 つのルートの自動読み込みはファイルベースです。つまり、コントローラー名とメソッド名を書き込んだ後は、追加の構成を行わずにルートに直接アクセスできます。

1. Thinkphp のルーティングは自動的にロードされます

tp はモジュール/コントローラー/メソッドのファイル名に従って自動的にロードされます

module?/controller/Action
たとえば、 Adminモジュールに続きます 次に、AdlistController.class.phpのindexメソッド 彼のルートは、

Admin/adList/index

##2 として自動的にロードされます。Thinkjs のルートは、自動的に

## としてロードされます。 ノードのバックエンドルーティングの自動読み込みについて説明する記事#コントローラ ファイルの自動ロード ロジック

1)、アプリケーションの初期化、インスタンスの作成....

2)、コントローラ ディレクトリのトラバース、コントローラのロード

ディレクトリ ファイルに対応するエクスポートされたクラスのマップを取得します。

たとえば、Controller ディレクトリ内で 彼はモジュール、コントローラー、メソッドをロードし、アプリにハングします。

{
  '/order': [class default_1 extends default_1],
  '/user': [class default_1 extends default_1]
}


3. コントローラーのマッチング部分

ノードのバックエンドルーティングの自動読み込みについて説明する記事前のステップは、thinkjs アプリケーションの起動フェーズ中に実行されます。

このステップ コントローラーのマッチング部分 は、リクエストが届いたときに実行されることです。

つまり、リクエストが来ると、それが最初に通過し、Think-router はモジュール、コントローラー、アクションを解析して ctx にハングします。

ここでは、ctx 上のこのリクエストのモジュール、コントローラー、アクションを取得し、起動時にアプリにハングしているモジュール、コントローラー、アクション、リストと照合し、存在する場合はそれを実行します。 think-controller のマッチング ロジックの詳細については、

github.com/thinkjs/thi…

thinkjs と koa-router の違いを参照してください。ルート マッチング

1. think-router が解析した後、think-controller はマッチングを実行します。これは動的マッチングです。

2. koa-router がルートと一致したら、koa-compose を使用して小さなオニオン リングを組み立てて
! 私の理解では、プログラムの開始時にシーケンスが登録されると理解しています image.png



#概要: thinkjs は最初にコントローラーとメソッドを読み込み、最後にリクエストが届いたら

think- を使用します。コントローラノードのバックエンドルーティングの自動読み込みについて説明する記事 最初にモジュール/コントローラを照合し、次にメソッドを照合します。存在する場合は実行されます。存在しない場合は、404

ノードのバックエンドルーティングの自動読み込みについて説明する記事

2 になります。 Egg を使用します 修正版では、デコレータ ルートを例として自動ロードします

デコレータの書き方は Java spring のアノテーションに似ています ノード フレームワーク内nestjs

midwayjs はデコレータ ルーティングを完全に採用しています。

  • 写法比较优雅
  • 建议控制器的文件名和控制器名字保持一致, 这样你找api也比较好找 比如控制的文件名字叫 home.ts , 那你控制器注册也写 @controller('/home') 来保持一致。

1、 控制器装饰器 @controller('/order')

'use strict';

import { Context } from 'egg';
import BaseController from './base';
import { formatDate } from '~/app/lib/utils';
import { SelfController, Get } from './../router'

@SelfController('/home')
export default class HomeController extends BaseController {
  [x: string]: any;
  @validate()
  @Get("/")
  public async index(): Promise<void> {}
  
}

2、方法装饰器 @Get('/export')、 @Post('/list')

get接口 就是 @Get()

post的接口 就是 @Post()

  @Get("/")
  public async index(): Promise<void> {}

  @Post("/update")
  public async update(): Promise<void> {}

3、装饰器路由统一注册

这里统一按egg的方法循环注册路由

'use strict';

import { Application, Context } from 'egg';
import 'reflect-metadata';

const CONTROLLER_PREFIX: string = '';
const methodMap: Map<string, any> = new Map<string, any>();
const rootApiPath: string = '';

interface CurController {
  pathName: string;
  fullPath: string;
}

/**
 * controller 装饰器,设置api公共前缀
 * @param pathPrefix {string}
 * @constructor
 */
export const SelfController = (pathPrefix?: string): ClassDecorator => (targetClass): void => {
  // 在controller上定义pathPrefix的元数据
  // https://github.com/rbuckton/reflect-metadata

  (Reflect as any).defineMetadata(CONTROLLER_PREFIX, pathPrefix, targetClass);
};

const methodWrap = (path: string, requestMethod: string): MethodDecorator => (target, methodName): void => {
  // 路由装饰器参数为空时,路由为方法名
  const key = path ? `${requestMethod}·${path}·${String(methodName)}` : `${requestMethod}·${String(methodName)}·/${String(methodName)}`;
  methodMap.set(key, target);
};

// Post 请求
export const Post = (path: string = ''): MethodDecorator => methodWrap(path, 'post');

// Get 请求
export const Get = (path: string = ''): MethodDecorator => methodWrap(path, 'get');

export default (app: Application): void => {
  const { router } = app;
  // 遍历methodMap, 注册路由
  methodMap.forEach((curController: CurController, configString: string) => {
    // 请求方法, 请求路径, 方法名 
    const [ requestMethod, path, methodName ] = configString.split(`·`);
    // 获取controller装饰器设置的公共前缀
    // 如果controller没有添加SelfController装饰器,则取文件名作为路径
    let controllerPrefix: string | undefined | null = (Reflect as any).getMetadata(CONTROLLER_PREFIX, curController.constructor);
    if (!(Reflect as any).hasMetadata(CONTROLLER_PREFIX, curController.constructor)) {
      controllerPrefix = `/${curController.pathName.split(`.`).reverse()[0]}`;
    }
    const func: (this: Context, ...args: any[]) => Promise<any> = async function (...args: any[]): Promise<any> {
      return new (curController.constructor as any)(this)[methodName](...args);
    };
    // 注册路由
    router[requestMethod](rootApiPath + controllerPrefix + path, func);
  });
};

建议使用node写服务直接上midwayjs或者nestjs

总结

通过如上比较,相信你对think系列框架堵文件的路由自动加载和装饰器的路由加载,有了一定了解, 他们的这种设计思想值得学习吧, 希望对你有所启发。

还有我认为装饰器的路由写起来,比较优雅, 不知道各位小伙伴怎么看,评论区说说?

更多node相关知识,请访问:nodejs 教程

以上がノードのバックエンドルーティングの自動読み込みについて説明する記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。