淺談node.js的後端路由自動載入
本文適宜人群
#有一定基礎的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个
寫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); };
常見的路由自動載入
接觸下來,我發現有幾個框架用不同方法實現了路由自動載入。一、think系列
第一個是thinkPHP和thinkjs, 參考連結他兩的關係屬於是thinkjs是後來依照thinkPHP的想法設計開發的。 他兩路由自動載入屬於基於檔案的, 就是說你按控制器的名字和方法名寫好,直接就可以存取路由,不需要額外的設定。1、thinkphp的路由自動載入
tp是按模組/控制器/方法檔案名稱自動載入module?/controller/Action
Admin/adList/index
#2、thinkjs的路由自動載入
控制器檔案檔案自動載入邏輯1)、套用初始化,建立實例....
例如Controller目錄下
他會載入出來模組、控制器、方法掛在他的app上。
{ '/order': [class default_1 extends default_1], '/user': [class default_1 extends default_1] }
3、控制器匹配部分
#上一步是在thinkjs應用程式啟動階段做的事情。 這一步控制器匹配部分 是在當請求進來的時候做的事情。
thinkjs和koa-router路由匹配的區別
1、 think think-router解析完, think-controller去匹配執行, 他這個是動態匹配。2、koa-router 配對到路由後, 自己再用koa-compose組裝一個小洋蔥圈去執行
! 這種我的理解是程式啟動就註冊好的順序
image.png
think-controller 去先匹配模組/控制器,再匹配方法, 如果有的話就幫你執行,沒有的話,就404
二、以egg改造版為例裝飾器的路由自動載入
裝飾器的寫法類似於java spring中的註解
node框架中 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> {} }</void>
2、方法装饰器 @Get('/export')、 @Post('/list')
get接口 就是 @Get()
post的接口 就是 @Post()
@Get("/") public async index(): Promise<void> {} @Post("/update") public async update(): Promise<void> {}</void></void>
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>
建议使用node写服务直接上midwayjs或者nestjs
总结
通过如上比较,相信你对think系列框架堵文件的路由自动加载和装饰器的路由加载,有了一定了解, 他们的这种设计思想值得学习吧
, 希望对你有所启发。
还有我认为装饰器的路由写起来,比较优雅, 不知道各位小伙伴怎么看,评论区说说?
更多node相关知识,请访问:nodejs 教程!
以上是淺談node.js的後端路由自動載入的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

要連接 MySQL 資料庫,需要遵循以下步驟:安裝 mysql2 驅動程式。使用 mysql2.createConnection() 建立連接對象,其中包含主機位址、連接埠、使用者名稱、密碼和資料庫名稱。使用 connection.query() 執行查詢。最後使用 connection.end() 結束連線。

Node.js 安裝目錄中有兩個與 npm 相關的文件:npm 和 npm.cmd,區別如下:擴展名不同:npm 是可執行文件,npm.cmd 是命令視窗快捷方式。 Windows 使用者:npm.cmd 可以在命令提示字元中使用,npm 只能從命令列執行。相容性:npm.cmd 特定於 Windows 系統,npm 跨平台可用。使用建議:Windows 使用者使用 npm.cmd,其他作業系統使用 npm。

Node.js 中存在以下全域變數:全域物件:global核心模組:process、console、require執行階段環境變數:__dirname、__filename、__line、__column常數:undefined、null、NaN、Infinity、-Infinity

Node.js 和 Java 的主要差異在於設計和特性:事件驅動與執行緒驅動:Node.js 基於事件驅動,Java 基於執行緒驅動。單執行緒與多執行緒:Node.js 使用單執行緒事件循環,Java 使用多執行緒架構。執行時間環境:Node.js 在 V8 JavaScript 引擎上運行,而 Java 在 JVM 上運行。語法:Node.js 使用 JavaScript 語法,而 Java 使用 Java 語法。用途:Node.js 適用於 I/O 密集型任務,而 Java 適用於大型企業應用程式。

PiNetwork節點詳解及安裝指南本文將詳細介紹PiNetwork生態系統中的關鍵角色——Pi節點,並提供安裝和配置的完整步驟。 Pi節點在PiNetwork區塊鏈測試網推出後,成為眾多先鋒積極參與測試的重要環節,為即將到來的主網發布做準備。如果您還不了解PiNetwork,請參考Pi幣是什麼?上市價格多少? Pi用途、挖礦及安全性分析。什麼是PiNetwork? PiNetwork項目始於2019年,擁有其專屬加密貨幣Pi幣。該項目旨在創建一個人人可參與

Node.js 專案的伺服器部署步驟:準備部署環境:取得伺服器存取權限、安裝 Node.js、設定 Git 儲存庫。建置應用程式:使用 npm run build 產生可部署程式碼和相依性。上傳程式碼到伺服器:透過 Git 或檔案傳輸協定。安裝依賴項:SSH 登入伺服器並使用 npm install 安裝應用程式相依性。啟動應用程式:使用 node index.js 等命令啟動應用程序,或使用 pm2 等進程管理器。設定反向代理(可選):使用 Nginx 或 Apache 等反向代理路由流量到應用程式
