原文地址: http://www.cnblogs.com/hbzyin/p/7381530.html
引入
伴随着nodejs流行,往日被无数后端程序员所不屑诟病的脚本语言Javascript的重要性与日俱增,2017年IBM一项调查数据显示,目前为止这个小巧灵活的语言已经跃升至用户量第一的编程语言;
Express作为nodejs官方首推的Web框架,也发挥出了巨大的潜力,Express团队现在正在开发更加小巧灵活的下一代nodejs框架KOA,相信也会让很多开发者眼前一亮。
为什么中间件这么重要,试想以下场景,如何解决:
1.开发过程中在处理http请求过程中,我们需要对请求对象、响应对象做某些特殊预处理工作,最后才会将处理的结果作为响应发送给请求;
2.请求处理http请求时,需要对所有的请求进行预先处理,比如检查请求的头信息是否存在必须的字段,检验请求的合法性,并做响应拦截过滤;
基本上有两种方案可以解决以上问题:
- 在每处请求响应出都定义中间处理函数,最终做出响应;
- 定义全局的中间处理函数,在各处请求响应中进行引用;
是的,express中间件要解决的问题正是我们以上的需求。
简介
Express是一个路由中间件Web框架,其自身只具有最低程度的功能,即:一系列中间件函数的调用。
express 中间件函数的特点及作用
- 特点:中间件函数能够访问请求对象(req)、响应对象(res)、下一个中间件函数(next);中间件默认按载入顺序依次执行,直到请求响应循环结束;
- 作用:①对请求对象进行处理;②对响应对象进行处理;③执行任意自定义功能;④调用下一个中间件;⑤结束请求响应循环;
- 中间件种类:①应用层中间件;②路由层中间件;③错误处理中间件;④内置中间件;⑤第三方中间件
1.中间件示例
先来看一个最最简单的Hello world Express应用程序示例:
var express=require('express');
var app=express();
app.get('/',function(req,res){
res.send('Hello world!')
})
app.listen(3000);
现在我们用一个最简单的中间件来实现:在GET 方法请求根路径/
时,先在服务窗口打印出'Response with middleware is working ok.',再响应输出’Hello World!’
var express=require('express');
var app=express();
app.get('/',function(req,res,next){
console.log('Response with middleware is working ok.');
next();
},function(req,res){
res.send('Hello world!')
})
app.listen(3000);
2. 中间件使用方法
- 在各个响应请求处理处单独定义中间处理函数,如上面的例子;
- 采用express.use()载入中间件函数,从载入位置开始,后续执行的请求响应循环都会执行该处的中间件函数;
如前文中场景2,在所有请求响应前在服务窗口打印出请求的log信息,如当前时间;
var express=require('express');
var app=express();
var logTime=function(req,res,next){
console.log(Date.now());
next();
};
app.use(logTime);
app.get('/',function(req,res){
res.send('This is response from server.')
})
app.listen(3000);
3. 中间件种类
express中应用层中间件即最常用的中间件,如上Hello world示例;路由中间件、第三方中间件与应用层中间件基本一致,不同之处在于,第三方中间件载入时需要提前引入,此时与引入的应用层中间件一致;这里对错误处理、内置中间件稍作说明;
- 错误处理中间件
- 错误处理中间件的定义与其他中间件函数基本相同,差别在于错误处理中间件函数有4个参数,(err,req,res,next)
- 错误处理中间件通常在所有其他中间件之后进行载入;
- Express 内附有一个缺省的错误处理中间件(处理程序),其位置位于中间函数集的末尾
错误处理中间件如下:
app.use(function(err,req,res,next){
console.log(err.stack);
res.status(500).send('Something broke!')
})
- 内置中间件
Express内置的中间件函数都已单独模块形式提供;目前仅依赖express.static(root,[options])
负责提供Express应用程序的静态资源;
先来看一个options对象的配置:
var options={
dotfiles:'ignore',
etag:false,
extensions:['htm','html'],
index:false,
maxAge:'1d',
redirect:false,
setHeaders:function(res,path,stst){
res.set('x-timestamp',Date.now())
}
}
app.use(express.static('public',options))
options对象具有以下属性:
序号 | 属性名称 | 类型 | 默认值 | 作用 |
---|---|---|---|---|
1 | dotfiles | String | 'ignore' | 是否对外输出以. 开头的文件 |
2 | etag | Boolean | true | 启用或开启etag |
3 | extensions | Array | [] | 用于设置后备文件扩展名 |
4 | index | 混合 | ‘index.html’ | 发送文件索引目录 |
5 | lastModified | Boolean | true | 将Last-Modified的头设置为操作系统对应文件上次修改的有效值 |
6 | maxAge | Number | 0 | 设置Cache-Control头的max-age属性(ms) |
7 | redirect | Boolean | true | 当前路径是目录是中定向到结尾的/ |
8 | setHeaders | function(){} | 设置随文件一起提供的HTTP头信息 |
每个应用程序,可以对应多个静态目录,如:
app.use(express.static('public'));
app.use(express.static('share'));
app.use(express.static('files'));
4. 其他:
- 中间件会按照载入的位置及顺序进行顺序执行,亦即中间件的载入位置顺序都会影响程序的处理结果;
- 中间件默认会一次执行,直到请求响应循环结束,亦即处理程序在遇到响应结束/响应发送的位置结束,而不会继续后续的中间件函数;
- 中间件必须通过
next()
来调用后续中间件,否则响应将处于挂起状态; - 中间件可通过
next('route')
跳过当前路由 中间件堆栈中剩余的中间件函数,将控制权传递给下一个路由;(该方法仅在使用app.METHOD()、router.METHOD()函数载入的中间件函数有效); - express中定义了9种响应方法,来结束请求响应循环,具体如下:
序号 | 方法名 | 说明 |
---|---|---|
1 | res.send() | 发送各种类型的响应 |
2 | res.senFile() | 发送八位元流形式的文件 |
3 | res.sendStatus() | 设置响应状态码,并以响应主体形式发送其字符串表示 |
4 | res.json() | 发送json响应 |
5 | res.jsonp() | 在jsonp的支持下,发送json响应 |
6 | res.render() | 呈现视图模板 |
7 | res.redirect() | 重定向请求 |
8 | res.download() | 提示将要下载文件 |
9 | res.end() | 结束响应进程 |
--END