Table des matières
Cet article convient aux personnes
难易程度
背景
常见的路由自动加载
thinkjs和koa-router路由匹配的区别
Niveau de difficulté
🎜Chargement automatique de route commune🎜
🎜La différence entre thinkjs et la correspondance de routage koa-router🎜
总结
Maison interface Web js tutoriel Une brève discussion sur le chargement automatique des routes back-end dans node.js

Une brève discussion sur le chargement automatique des routes back-end dans node.js

Oct 11, 2022 pm 07:48 PM
nodejs node.js node

Une brève discussion sur le chargement automatique des routes back-end dans node.js

Cet article convient aux personnes

Développeurs Node.js ayant une certaine base有一定基础的Node.js开发人员

难易程度

中等

背景

今天来谈谈node后端中路由的问题。【相关教程推荐:nodejs视频教程

我们前端同学或者是nodejs服务端的同学,在你们使用express和koajs写接口的时候, 咱们是不都要写路由 比如如下

登录接口router.post('/user/login', user.login);

获取用户信息接口router.get('/user/info', checkAuth, user.xxx);

这种写法很常见, 先注册路由,再指定后续要执行的中间件方法。

可是当接口越来越多,比如有1000个接口, 就得这样注册1000次,多了我认为是一件很麻烦且不优雅的事情

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个
Copier après la connexion

写1000个接口就要在router.js里注册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);
};
Copier après la connexion

**这种项目扩大时候, 我认为这种配置会显得很冗余,所以就需要实现一种路由自动加载的机制来改善它优化它。

1、提升效率

2、更优雅的编写

常见的路由自动加载

接触下来, 我发现有几个框架用不同方法实现了路由自动加载。

一、think系列

第一个是thinkPHP和thinkjs, 参考链接 thinkjs.org/zh-cn/doc/3…

他两的关系属于是thinkjs是后来按照thinkPHP的思想设计开发的。

他两路由自动加载属于基于文件的, 就是说你按控制器的名字和方法名写好,直接就可以访问路由,不需要额外的配置。

1、thinkphp的路由自动加载

tp是 按模块/控制器/方法文件名 自动加载

module?/controller/Action
Copier après la connexion

比方下面这个Admin模块下, AdlistController.class.php里 index方法 他的路由就会自动加载为 Admin/adList/index

Une brève discussion sur le chargement automatique des routes back-end dans node.js

2、thinkjs的路由自动加载

控制器文件文件自动加载逻辑

1)、应用初始化,创建实例
....

2)、遍历控制器目录, 加载控制器

得到目录文件对应的导出class的 Map
例如 Controller目录下 他会加载出来模块、控制器、方法挂在他的app上。

Une brève discussion sur le chargement automatique des routes back-end dans node.js

{
  '/order': [class default_1 extends default_1],
  '/user': [class default_1 extends default_1]
}
Copier après la connexion

3、控制器匹配部分

上一步是在thinkjs应用启动阶段做的事情。

这一步 控制器匹配部分 是在当请求进来的时候做的事情。

就是当请求进来,会先进过,think-router 把module, controller, action ,解析出来挂在ctx上。

在这里拿ctx上本次请求的module, controller, action去和启动时挂在app的 module, controller, action,列表去匹配, 如果有就执行。

think-controller的匹配逻辑详见 github.com/thinkjs/thi…

thinkjs和koa-router路由匹配的区别

1、 think  think-router解析完, think-controller去匹配执行, 他这个是动态匹配。
2、koa-router 匹配到路由后, 自己再用koa-compose组装一个小洋葱圈去执行
! 这种我的理解是程序启动就注册好的顺序image.png

Une brève discussion sur le chargement automatique des routes back-end dans node.jsUne brève discussion sur le chargement automatique des routes back-end dans node.js

总结:thinkjs是先把你的控制器和方法加载出来, 最后当请求进来的时候,利用think-controller

Niveau de difficulté

Moyen

Contexte

Aujourd'hui, parlons des problèmes de routage dans le backend du nœud. [Tutoriels associés recommandés : tutoriel vidéo nodejs]Nos camarades de classe front-end ou nodejs Étudiants côté serveur, lorsque vous utilisez express et koajs pour écrire des interfaces, nous n'avons pas besoin d'écrire des routes, par exemple comme suit

🎜Interface de connexion router.post('/user/login', user.login );🎜🎜Obtenir l'interface d'informations utilisateurrouter.get('/user/info', checkAuth, user.xxx);🎜🎜Cette méthode d'écriture est très courante. Enregistrez d'abord la route. , puis spécifiez les méthodes d'exécution ultérieures. 🎜🎜🎜Mais quand il y a de plus en plus d'interfaces, par exemple 1000 interfaces, vous devez vous inscrire comme ça 1000 fois. S'il y a plus d'interfaces, je pense que c'est une chose très gênante et inélégante🎜🎜🎜exemple d'enregistrement de routage koa&express. 🎜
'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> {}
  
}</void>
Copier après la connexion
Copier après la connexion
🎜🎜write Est-ce que 1 000 interfaces doivent être enregistrées 1 000 fois dans router.js ? 🎜🎜🎜exemple d'enregistrement de route eggjs🎜
  @Get("/")
  public async index(): Promise<void> {}

  @Post("/update")
  public async update(): Promise<void> {}</void></void>
Copier après la connexion
Copier après la connexion
🎜**Lorsque ce type de projet se développera, je pense que cette configuration deviendra très redondante, il est donc nécessaire d'implémenter un mécanisme de chargement automatique de route pour l'améliorer et l'optimiser. 🎜🎜1. Améliorer l'efficacité🎜🎜2. Écriture plus élégante🎜

🎜Chargement automatique de route commune🎜

🎜Après avoir pris contact, j'ai découvert qu'il existe plusieurs frameworks qui utilisent différentes méthodes pour implémenter le chargement automatique de route. 🎜🎜🎜🎜1. Série Think 🎜🎜🎜🎜Le premier est thinkPHP et thinkjs, lien de référence thinkjs.org/zh-cn/doc/3…🎜🎜La relation entre les deux appartient à thinkjs et plus tard Il est conçu et développé selon la pensée de thinkPHP. 🎜🎜Le chargement automatique des deux autres routes est basé sur un fichier, ce qui signifie qu'après avoir écrit le nom du contrôleur et le nom de la méthode, vous pouvez accéder directement à la route sans aucune configuration supplémentaire. 🎜🎜🎜1. La route de thinkphp est automatiquement chargée🎜🎜🎜tp est automatiquement chargé en fonction du nom du fichier module/contrôleur/méthode🎜
'use strict';

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

const CONTROLLER_PREFIX: string = '';
const methodMap: Map<string> = new Map<string>();
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);
  });
};</any></any></string></string>
Copier après la connexion
Copier après la connexion
🎜Par exemple, sous le module Admin ci-dessous, la méthode d'index dans AdlistController.class.php Son itinéraire sera automatiquement chargé en tant que Admin/adList/index🎜🎜Une brève discussion sur le chargement automatique des routes back-end dans node.js🎜🎜🎜2. Chargement automatique des routes thinkjs🎜🎜🎜Logique de chargement automatique du fichier du contrôleur🎜🎜1), initialisation de l'application, création d'instance
.. ..🎜🎜2), parcourez le répertoire du contrôleur, chargez le contrôleur🎜🎜 et récupérez la Map de la classe exportée correspondant au fichier répertoire
Par exemple, dans le répertoire Controller Il chargera les modules, les contrôleurs et les méthodes et les accrochera sur son application. 🎜🎜Une brève discussion sur le chargement automatique des routes back-end dans node.js🎜rrreee🎜 🎜3. Pièce de correspondance du contrôleur🎜🎜🎜L'étape précédente est effectuée lors de la phase de démarrage de l'application thinkjs. 🎜🎜Cette étape Pièce de correspondance du contrôleur est effectuée lorsque la demande arrive. 🎜🎜C'est-à-dire que lorsqu'une requête arrive, elle sera transmise en premier. Think-router analyse le module, le contrôleur, l'action et le suspend sur ctx. 🎜🎜Ici, prenez le module, le contrôleur et l'action de cette requête sur ctx et faites-les correspondre avec le module, le contrôleur, l'action et la liste accrochés dans l'application au démarrage. S'il y en a un, exécutez-le. 🎜🎜La logique de correspondance de Think-controller est détaillée dans github.com/thinkjs/thi…🎜
🎜La différence entre thinkjs et la correspondance de routage koa-router🎜
🎜1. pense Après l'analyse de -router, think-controller effectue une correspondance. Il s'agit d'une correspondance dynamique.
2. Une fois que koa-router correspond à l'itinéraire, vous pouvez utiliser koa-compose pour assembler une petite rondelle d'oignon pour l'exécution
 ! https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/17afb9d562bd48b4ae5a6e97dd886fe8~tplv-k3u1fbpfcp-zoom-1.image" target="_blank" textvalue="image.png">image.png a>🎜🎜Une brève discussion sur le chargement automatique des routes back-end dans node.js🎜🎜Résumé : thinkjs est Chargez d'abord votre contrôleur et vos méthodes. Enfin, lorsque la requête arrive, utilisez think-controller pour faire correspondre d'abord le module/contrôleur, puis la méthode s'il y en a une, elle sera exécutée pour vous. Sinon, juste 404🎜🎜🎜🎜 2. En prenant comme exemple la version modifiée d'oeuf, l'itinéraire du décorateur est automatiquement chargé🎜🎜🎜🎜🎜L'écriture du décorateur est similaire aux annotations dans java spring🎜🎜

node框架中 nestjsmidwayjs已经全面拥抱了装饰器路由。

  • 写法比较优雅
  • 建议控制器的文件名和控制器名字保持一致, 这样你找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> {}
  
}</void>
Copier après la connexion
Copier après la connexion

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

get接口 就是 @Get()

post的接口 就是 @Post()

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

  @Post("/update")
  public async update(): Promise<void> {}</void></void>
Copier après la connexion
Copier après la connexion

3、装饰器路由统一注册

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

'use strict';

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

const CONTROLLER_PREFIX: string = '';
const methodMap: Map<string> = new Map<string>();
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);
  });
};</any></any></string></string>
Copier après la connexion
Copier après la connexion

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

总结

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

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

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Nodejs est-il un framework backend ? Nodejs est-il un framework backend ? Apr 21, 2024 am 05:09 AM

Node.js peut être utilisé comme framework backend car il offre des fonctionnalités telles que des performances élevées, l'évolutivité, la prise en charge multiplateforme, un écosystème riche et une facilité de développement.

Comment connecter Nodejs à la base de données MySQL Comment connecter Nodejs à la base de données MySQL Apr 21, 2024 am 06:13 AM

Pour vous connecter à une base de données MySQL, vous devez suivre ces étapes : Installez le pilote mysql2. Utilisez mysql2.createConnection() pour créer un objet de connexion contenant l'adresse de l'hôte, le port, le nom d'utilisateur, le mot de passe et le nom de la base de données. Utilisez connection.query() pour effectuer des requêtes. Enfin, utilisez connection.end() pour mettre fin à la connexion.

Quelle est la différence entre les fichiers npm et npm.cmd dans le répertoire d'installation de nodejs ? Quelle est la différence entre les fichiers npm et npm.cmd dans le répertoire d'installation de nodejs ? Apr 21, 2024 am 05:18 AM

Il existe deux fichiers liés à npm dans le répertoire d'installation de Node.js : npm et npm.cmd. Les différences sont les suivantes : différentes extensions : npm est un fichier exécutable et npm.cmd est un raccourci de fenêtre de commande. Utilisateurs Windows : npm.cmd peut être utilisé à partir de l'invite de commande, npm ne peut être exécuté qu'à partir de la ligne de commande. Compatibilité : npm.cmd est spécifique aux systèmes Windows, npm est disponible multiplateforme. Recommandations d'utilisation : les utilisateurs Windows utilisent npm.cmd, les autres systèmes d'exploitation utilisent npm.

Quelles sont les variables globales dans nodejs Quelles sont les variables globales dans nodejs Apr 21, 2024 am 04:54 AM

Les variables globales suivantes existent dans Node.js : Objet global : global Module principal : processus, console, nécessiter Variables d'environnement d'exécution : __dirname, __filename, __line, __column Constantes : undefined, null, NaN, Infinity, -Infinity

Y a-t-il une grande différence entre nodejs et java ? Y a-t-il une grande différence entre nodejs et java ? Apr 21, 2024 am 06:12 AM

Les principales différences entre Node.js et Java résident dans la conception et les fonctionnalités : Piloté par les événements ou piloté par les threads : Node.js est piloté par les événements et Java est piloté par les threads. Monothread ou multithread : Node.js utilise une boucle d'événements monothread et Java utilise une architecture multithread. Environnement d'exécution : Node.js s'exécute sur le moteur JavaScript V8, tandis que Java s'exécute sur la JVM. Syntaxe : Node.js utilise la syntaxe JavaScript, tandis que Java utilise la syntaxe Java. Objectif : Node.js convient aux tâches gourmandes en E/S, tandis que Java convient aux applications de grande entreprise.

Enseignement du nœud PI: Qu'est-ce qu'un nœud PI? Comment installer et configurer le nœud PI? Enseignement du nœud PI: Qu'est-ce qu'un nœud PI? Comment installer et configurer le nœud PI? Mar 05, 2025 pm 05:57 PM

Explication détaillée et guide d'installation pour les nœuds de pignon Cet article introduira l'écosystème de pignon en détail - nœuds PI, un rôle clé dans l'écosystème de pignon et fournir des étapes complètes pour l'installation et la configuration. Après le lancement du réseau de test de la blockchain pèse, les nœuds PI sont devenus une partie importante de nombreux pionniers participant activement aux tests, se préparant à la prochaine version du réseau principal. Si vous ne connaissez pas encore Pinetwork, veuillez vous référer à ce qu'est Picoin? Quel est le prix de l'inscription? PI Utilisation, exploitation minière et sécurité. Qu'est-ce que Pinetwork? Le projet Pinetwork a commencé en 2019 et possède sa pièce exclusive de crypto-monnaie PI. Le projet vise à en créer un que tout le monde peut participer

Nodejs est-il un langage de développement back-end ? Nodejs est-il un langage de développement back-end ? Apr 21, 2024 am 05:09 AM

Oui, Node.js est un langage de développement backend. Il est utilisé pour le développement back-end, notamment la gestion de la logique métier côté serveur, la gestion des connexions à la base de données et la fourniture d'API.

Comment déployer le projet nodejs sur le serveur Comment déployer le projet nodejs sur le serveur Apr 21, 2024 am 04:40 AM

Étapes de déploiement de serveur pour un projet Node.js : Préparez l'environnement de déploiement : obtenez l'accès au serveur, installez Node.js, configurez un référentiel Git. Créez l'application : utilisez npm run build pour générer du code et des dépendances déployables. Téléchargez le code sur le serveur : via Git ou File Transfer Protocol. Installer les dépendances : connectez-vous en SSH au serveur et installez les dépendances de l'application à l'aide de npm install. Démarrez l'application : utilisez une commande telle que node index.js pour démarrer l'application ou utilisez un gestionnaire de processus tel que pm2. Configurer un proxy inverse (facultatif) : utilisez un proxy inverse tel que Nginx ou Apache pour acheminer le trafic vers votre application

See all articles