특정 기초를 갖춘 Node.js 개발자
有一定基础的Node.js开发人员
中等
今天来谈谈node后端中路由的问题。【相关教程推荐:nodejs视频教程】
我们前端同学或者是nodejs服务端的同学,在你们使用express和koajs写接口的时候, 咱们是不都要写路由 比如如下
登录接口router.post('/user/login', user.login);
获取用户信息接口router.get('/user/info', checkAuth, user.xxx);
Medium
오늘은 노드 백엔드의 라우팅 문제에 대해 이야기해 보겠습니다. [추천 관련 튜토리얼: nodejs 동영상 튜토리얼]
프론트엔드 급우 또는 동급생 nodejs 서버, express 및 koajs를 사용하여 인터페이스를 작성할 때 다음과 같은 경로를 작성할 필요가 없습니다.Login 인터페이스router.post('/user/login', user.login);<p></p> 사용자 정보 가져오기 인터페이스 <code>router.get('/user/info', checkAuth, user.xxx);
이 작성 방법은 먼저 경로를 등록한 다음 매우 일반적입니다. 나중에 실행할 미들웨어 방법을 지정합니다.
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个
write 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. Think 시리즈Admin/adList/index
첫 번째는 thinkPHP와 thinkjs, 참조 링크는 thinkjs.org/zh-cn/doc/3…
둘의 관계는 thinkjs와 이후의 thinkPHP에 속합니다. 설계 및 개발되었습니다.
다른 두 경로의 자동 로딩은 파일 기반이므로 컨트롤러 이름과 메서드 이름을 작성한 후 추가 구성 없이 경로에 직접 액세스할 수 있습니다.1.thinkphp의 경로가 자동으로 로드됩니다
tp가 모듈/컨트롤러/메소드 파일 이름에 따라 자동으로 로드됩니다
module?/controller/Action
예를 들어 아래 Admin 모듈 아래에는 AdlistController.class.php의 index 메소드가 있습니다.
그의 경로는
2로 자동 로드되고, thinkjs 경로는 자동으로 로드됩니다.
컨트롤러 파일 파일 자동 로딩 로직
1), 애플리케이션 초기화, 인스턴스 생성 控制器匹配部分
是在当请求进来的时候做的事情。
就是当请求进来,会先进过,think-router 把module, controller, action ,解析出来挂在ctx上。
在这里拿ctx上本次请求的module, controller, action去和启动时挂在app的 module, controller, action,列表去匹配, 如果有就执行。
think-controller的匹配逻辑详见 github.com/thinkjs/thi…
1、 think think-router解析完, think-controller去匹配执行, 他这个是动态匹配。
2、koa-router 匹配到路由后, 自己再用koa-compose组装一个小洋葱圈去执行
! 这种我的理解是程序启动就注册好的顺序image.png
总结:thinkjs是先把你的控制器和方法加载出来, 最后当请求进来的时候,利用think-controller
去先匹配模块/控制器,再匹配方法, 如果有的话就帮你执行,没有的话,就404
二、以egg改造版为例 装饰器的路由自动加载
装饰器的写法类似于 java spring中的注解
node框架中 nestjs
和midwayjs
....
{ '/order': [class default_1 extends default_1], '/user': [class default_1 extends default_1] }
컨트롤러 매칭 부분
단계가 완료됩니다. 🎜🎜즉, 요청이 들어오면 Think-router가 모듈, 컨트롤러, 액션을 구문 분석하여 ctx에 정지시킵니다. 🎜🎜여기서 이 요청의 모듈, 컨트롤러, 액션을 ctx에서 가져와서 시작 시 앱에 걸려 있는 모듈, 컨트롤러, 액션, 목록과 일치시키면 실행하세요. 🎜🎜think-controller의 매칭 로직은 github.com/thinkjs/thi…🎜🎜think-controller
를 사용하여 먼저 모듈을 일치시킵니다. /controller, 그리고 메소드가 있으면 실행됩니다. 그렇지 않으면 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!