中间件的作用
请求到达express的服务器后,对请求进行预处理。
简易流程图
next()
next()往后匹配当前中间件堆栈的下一个
next('router') 往后匹配下一个中间件(越过当前中间件netx(router)后面的处理)
next(任意数据)express都会将其视为错误,并且跳过所有剩下无错误处理路由和中间件函数。
应用层中间件
应用级中间件绑定到 app 对象 使用 app.use() 和 app.METHOD(),其中, METHOD 是需要处理的 HTTP 请求的方法,例如 get(), put(), post()
app.use()不加地址筛选的话客户端发起任何请求,到达服务器后都会触发的中间件
next('router')
要从路由器中间件堆栈中跳过其余中间件功能,请调用next( ' route ')将控制权传递给下一条中间件
next( ' route ')只能在app.method()或者router.method()中间件有效果。
注:这里的methods()是指get() post()等等对于use()是不能用的
const express=require('express');
const app=express();
// 1应用级别的中间件
// 1.1不做任何限定的中间件 也叫全局中间件 只要请求了就会触发
const mv=function(request,response,next){
console.log("我是中简件");
next();
}
app.use(mv);
app.use((request,response,next)=>{
console.log("我是中间件2");
next();
});
// 1.2限定请求路径的中间件
app.use('/api',(request,response,next)=>{
console.log("我是中间件3");
next();});
// 1.3限定请求方法和请求路径的中间件 get() pust() patch() delete()
app.get('/api',(request,response,next)=>{
console.log("我是中间件4");
response.send({
state:'OK',
});
next();});
app.listen(8088,()=>{
console.log("启动成功");
})
// 1.4多个函数的处理
// 请求后会处理两个函数,一个中间件可以有多个中间件处理函数。
app.use("/user/:id",function(req, res, next) {
console.log("Request URL:", req.originalUrl);
next();
},function(req, res, next) {
console.log("Request Type:", req.method);
next();
});
// 1.5同一个路径处理多个中间件 请求成功时两个中间件都会触发。
app.get("/api/:id",function(req, res, next) {
console.log("ID:", req.params.id);
next();
},function(req, res, next) {
res.send("User Info");
});
app.get("/api/:id", function(req, res, next) {
res.end(req.params.id);});
// 1.6 next("router");
// res.render()函数用于呈现视图,并将呈现的HTML字符串发送给客户端。
// 这个代码的意思是id如果是0那么就放弃本次中间件的下面的数据从这里开始跳到下一个中间件开始执行。
app.get("/users/:id",function(req, res, next) {
if (req.params.id === "0") next("route");
else next();
},function(req, res, next) {
console.log('regular');
next();
});
app.get("/users/:id", function(req, res, next) {
console.log("pecial");
next();
});
// 1.7中间件也可以使用数组作为处理函数使用。
function response_one(request,response,next){
console.log("我是数组响应1");
next();
}
function response_two(request,response,next){
console.log("我是数组响应2");
next();
}
responseAll=[response_one,response_two]
app.get('/onedotseven',responseAll);
路由器级别的中间件
路由级中间件和应用级中间件一样,只是它绑定的对象为 express.Router()
路由级使用 router.use() 或 router.method() 加载。
应用级中间件的一些操作在路由中间件中也是一样可以使用的。
main.js
var app = express();
var router = express.Router();
// 没有挂载路径的中间件,通过该路由的每个请求都会执行该中间件
router.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
// 一个中间件栈,显示任何指向 /user/:id 的 HTTP 请求的信息
router.use('/user/:id', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next();
}, function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
// 一个中间件栈,处理指向 /user/:id 的 GET 请求
router.get('/user/:id', function (req, res, next) {
// 如果 user id 为 0, 跳到下一个路由
if (req.params.id == 0) next('route');
// 负责将控制权交给栈中下一个中间件
else next(); //
}, function (req, res, next) {
// 渲染常规页面
res.render('regular');
});
// 处理 /user/:id, 渲染一个特殊页面
router.get('/user/:id', function (req, res, next) {
console.log(req.params.id);
res.render('special');
});
// 将路由挂载至应用
app.use('/', router);
错误处理中间件
router.js
const express=require('express');
// 路由实例
const router=express.Router()
router.get('/foo',function(request,response,next){
try{
next.ok();//用来报错的错误函数。
response.send('get /foo');
console.log("foo_OK");
next();
}catch(err){
next(err);
}
})
module.exports=router
main.js
const express=require('express');
// 引入路由
const router =require("./routerMiddleware")
const app=express()
app.use(router);//把引入的router放入use就会生效。
//app.use('/api',router);// 为路由添加前缀
app.use(function(error,request,response,next){//四个形参缺一不可
console.log("错误",error);
response.status(500).json({
error:error.message
})
})
app.listen(8088,()=>{
console.log('服务器启动起来了。');
})
内置中间件
express本身就提供的中间件函数
自 Express 4.16.0 版本开始,Express 内置了 3 个常用的中间件,极大的提高了 Express 项目的开发效率和体验:
express.text() 解析Content-Type为text/plain格式的请求体
express.raw() 解析Content-Type为application/octet-stream格式的请求体
express.static() 快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS 样式等(无兼容性)
express.json() 解析 JSON 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)
express.urlencoded() 解析 URL-encoded 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)
第三方中间件
早期的 Express 内置了很多中间件。后来 Express 在 4.x 之后移除了这些内置中间件,官方把这些功能性中间件以包的形式单独提供出来。这样做的目的是为了保持 Express 本身极简灵活的特性,开发人员可以根据自己的需求去灵活的定制。下面是官方提供的一些常用的中间件解决方案。
官方中间件资源:http://expressjs.com/en/resources/middleware.html