关于express.js实现源码解读,版本为4.14。主要针对路由部分。Web框架最重要的模块是路由功能。该模块的目标是根据方法和路径匹配需要执行的方法,并在定义的方法中提供请求和响应的上下文。模块声明express中的路由模块由Router完成,通过调用Router()获取router的一个实例。路由器既是对象又是函数。原因是实现了C++中的()重载方法,本质上是指向对象。手柄方法。路由器的定义位于router/index.js中。//router/index.js-第42行varproto=module.exports=function(options){varopts=options||{};//类似于C++中的operator()functionrouter(req,res,next){router.句柄(请求,资源,下一个);}//...}接口定义路由器对外(也就是开发者)提供路由规则定义的接口:get、put等对应HTTP方法类,函数签名都是$method(path,fn(req,res),...),接口的方法是通过元编程动态定义和生成的。这样做的根本原因是可以使用变量的值来定义和调用方法名,也可以间接利用Java中的反射特性来实现这一点,在Spring框架中被广泛使用。//router/index.js-line507//创建Router#VERB函数//-->['get','post','put',...].foreachmethods.concat('all').forEach(function(method){//这样我们就可以写成'router.get(path,...)'proto[method]=function(path){//为我们定义的路由规则创建一个路由varroute=this.route(path)//将对应的handler映射到路由规则route[method].apply(route,slice.call(arguments,1));returnthis;};});路由定义在规则定义的接口中,其中,路由规则的定义需要路由器保存路由规则的信息,最重要的是方法、路径、匹配时的调用方法(以下简称作为处理程序)和其他详细信息。这些信息(也可以看作是配置)路由的保存是由Route对象完成的,一个Route对象包含了一条路由规则。Route对象由路由器对象的route()方法实例化并初始化并返回。//router/index.js-line491proto.route=functionroute(path){//创建Route的实例。varroute=newRoute(路径);//创建图层实例。varlayer=newLayer(path,{sensitive:this.caseSensitive,strict:this.strict,end:true},route.dispatch.bind(route));//层有对路由的引用。layer.route=路线;//路由器有一个由'route()'创建的层列表this.stack.push(layer);回程;};Route的成员变量包括path路径,以及HTTP方法的路由配置接口集合,这里和router中的技巧一样提供各类方法的注册函数,这里无所谓,只要route能获取路由配置的方法值,方法可以作为参数传入,也可以作为方法名调用。route()方法除了实例化一个Route之外,还会实例化一个Layer。这个Layer相当于Route对应的通用调度器。它封装了handlers的调用过程,先忽略。实际将处理程序传递给路由发生在第510行,这是上述路由提供的注册功能。由于可以在路由设置中传递多个处理程序,因此有必要保存一个处理程序列表。每个处理程序都由一个层对象封装,以隐藏异常处理和处理程序调用链的细节。所以路由保存了一个Layer数组,按照参数中声明handler的顺序存放。这里是Layer的第一个功能:在路由中封装一个handler,隐藏链式调用、异常处理等细节。//router/route.js-第190行for(vari=0;i
