ホームページ > 記事 > ウェブフロントエンド > ノードのバックエンドルーティングの自動読み込みについて説明する記事
難易度
バックグラウンド
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个
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メソッド
彼のルートは、
## としてロードされます。 #コントローラ ファイルの自動ロード ロジック
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 のマッチング ロジックの詳細については、
1. think-router が解析した後、think-controller はマッチングを実行します。これは動的マッチングです。
2. koa-router がルートと一致したら、koa-compose を使用して小さなオニオン リングを組み立ててthink- を使用します。コントローラ 最初にモジュール/コントローラを照合し、次にメソッドを照合します。存在する場合は実行されます。存在しない場合は、404
2 になります。 Egg を使用します 修正版では、デコレータ ルートを例として自動ロードしますデコレータの書き方は Java spring のアノテーションに似ています ノード フレームワーク内nestjs
とmidwayjs はデコレータ ルーティングを完全に採用しています。
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 サイトの他の関連記事を参照してください。