深入理解Express
来源:互联网 发布:台湾剧1983星星知我心 编辑:程序博客网 时间:2024/06/05 06:14
https://github.com/syaning/understanding-express
本文同时发布于我的博客
本文主要通过是对Express的一个较为深入的分析,至于对Express的源码分析,在我的Github上。本文的分析基于Express 4.12.3.
理解app
在使用Express的时候,我们通过如下方式创建一个应用:
var express = require('express');var app = express();app.listen(3000);
而在不使用框架的时候,通常的做法是:
var http = require('http');http.createServer(function(req, res) { res.write('hello world'); res.end(); }) .listen(8000);
通过查看源码,可以发现,express
实际上就是一个工厂函数,用来创建app
,而app
则就是createServer
的回调函数。相关源码如下:
// in express.jsfunction createApplication() { var app = function(req, res, next) { app.handle(req, res, next); }; // ... ... return app;}// in application.jsapp.listen = function(){ var server = http.createServer(this); return server.listen.apply(server, arguments);};
因此,在使用Express的时候,事实上,所有的请求都是交给app
,通过app.handle
来处理了。
通过分析application.js的源码,可以归纳出,app
主要有如下属性和方法:
settings
,{},主要是一些设置信息,相关方法有:set(setting, value)
,有value
的时候进行设置,无value
的时候进行获取get(setting)
enabled(setting)
disabled(setting)
enable(setting)
disable(setting)
cache
,{}engines
,{},设置模版引擎,相关方法有:engine(ext, fn)
locals
,{}mountpath
,字符串,相关方法有:use(path, app)
,会设置app
的mountpath
的值path()
,获取应用的绝对路径值
_router
,Router
对象,相关方法有(由于参数可以有多种形式,因此并未列出参数):route()
,创建一条路由,会调用Router.route
METHOD()
,创建一条路由,并调用VERB方法,会调用Router.route
all()
,创建一条路由,并调用所有的VERB方法,会调用Router.route
param()
,会调用Router.param
use()
,会调用Router.use
Router
app
有一个_router
属性,事实上就是一个Router
。Router
相当于是一个中间件容器,存放着各种各样的中间件,大体上,可以分为路由中间件和其它中间件。Router
的主要属性和方法有:
params
,{}param()
_params
,[]caseSensitive
,booleanmergeParam
,booleanstrcit
,booleanstack
,[],存放着所有的中间件,相关方法有:use()
,使用中间件,本质上是向stack
中添加一个Layer
对象route()
,创建路由中间件,本质上是创建一个Route
对象,并使用该Route
对象创建一个Layer
对象,将此layer
对象添加到stack
中METHOD()
,创建路由中间件,并添加处理函数,实际上是调用了route()
方法
每个中间件都是一个Layer
对象,Layer
对象的基本属性有:
handle
,function,表示中间件函数name
,string,中间件函数的名字,如果为匿名函数则为<anonymous>
params
,undefined,在执行match
的时候赋值path
,undefiend,在执行match
的时候赋值regexp
,RegExp,路径的正则表达形式keys
,[],保存的是路径中的参数及其相关的一些其它信息route
,如果是路由中间件,则该属性为一个Route
对象,否则为undefined
。该属性不在Layer
模块中定义,而是在Router
模块中生成实例后定义
路由机制
在Router
的stack
中,存放着多个中间件,每一个中间件都是一个Layer
对象,如果该中间件是一个路由中间件,则相应的Layer
对象的route
属性会指向一个Route
对象,表示一条路由。Route
的主要属性和方法有:
path
,string,表示路径stack
,[],存放的是Layer
对象,表示路由处理函数methods
,{},表明支持哪些HTTP方法,例如{ get: true }
,如果使用了all()
,则该属性值为{ _all: true }
需要注意的是,Route
的stack
与Router
的stack
存放的都是Layer
对象,但是这两种Layer
之间有少许差别,主要如下:
- 都具有
handle
,name
,params
,path
,regexp
,keys
属性,这几个属性都是在Layer
模块的构造函数中定义的 Router
中的Layer
对象具有route
属性,如果该属性不为undefined
,则表明为一个路由中间件;而Route
中的Layer
对象没有route
属性Route
中的Layer
对象具有method
属性,表明该路由函数的HTTP方法;而Router
中的Layer
对象没有method
属性Route
中的Layer
对象的keys
属性值均为[]
,regexp
属性值均为/^\/?$/i
,因为在Route
模块中创建Layer
对象时使用的是Layer('/', {}, fn)
创建路由的主要方法及其调用过程如下:
app.METHOD()
→router.route
→route.METHOD()
app.all()
→router.route
→route.METHOD()
app.route()
→router.route
例如:
app.all('/users', function() {});app.get('/users/:username', function() {});app.route('/test').get(function() {}).post(function() {});
对于同一路径的多次路由添加会创建多条路由,例如:
app.get('/users', function test() {});app.get('/users', function foo() {}, function bar() {});
该例子会创建两条路由,其中第一条路有一个处理函数,而第二条路由有两个处理函数。
请求处理
当请求到来时,处理过程是app.handle
→ router.handle
,事实上,app.handle
调用了router.handle
,而router.handle
的过程,则是依次对router.stack
中存放的中间件进行调用。示例图如下:
router.stack
中存的是一个个的Layer
对象,用来管理中间件。如果Layer
对象表示的是一个路由中间件,则其route
属性会指向一个Route
对象,而route.stack
中存放的也是一个个的Layer
对象,用来管理路由处理函数。
因此,当一个请求到来的时候,会依次通过router.stack
中的Layer
对象,如果遇到路由中间件,则会依次通过route.stack
中的Layer
对象。
对于router.stack
中的每个Layer
对象,会先判断是否匹配请求路径,如果不匹配,则跳过,继续下一个。在路径匹配的情况下,如果是非路由中间件,则执行该中间件函数;如果是路由中间件,则继续判断该中间件的路由对象能够处理请求的HTTP方法,如果不能够处理,则跳过继续下一个,如果能够处理则对route.stack
中的Layer
对象(与请求的HTTP方法匹配的)依次执行。示例图如下:
在中间件函数执行之前,会先对参数进行预处理,即router.process_params
。对于每个参数的预处理只会进行一次,但是由于每个layer执行之前都会有参数预处理的过程,因此有一个缓存系统,来记录哪些参数已经处理过了。
- 深入理解Express.js
- 深入理解 Express.js
- 深入理解 Express.js
- 深入理解Express.js
- 深入理解express框架
- 深入理解Express
- 深入理解express框架
- 深入理解express的中间件
- 【重拾】深入理解express框架
- node中Express的use深入理解
- 深入express,用express搭建路由
- express模块的理解
- 理解express中间件bodyparser
- express框架的理解
- 深入理解
- nodesj中 中间件express-session的理解
- Express MVC模式理解与项目结构
- Nodejs搭建服务器express框架理解
- 51nod 1257 背包问题 V3
- Node.js HelloWorld的小细节
- php可变变量
- 阿里云数据库挑战赛"SQL优化大师"获奖案例
- 用springBoot与dubbo、 zookeeper、redis整合做了一个弹幕网站
- 深入理解Express
- Java编程要点之 I/O 流详解
- Java 并发开发:Lock 框架详解
- 加入Webhacking.kr,从此赚取积分走上人生巅峰
- Java 异常处理的误区和经验总结
- Java 类加载机制详解
- 你需要理解的 Java 反射机制知识总结
- Java 泛型详解
- Java 动态代理深入解析