express()
express()
用来创建一个Express的程序。express()
方法是***express***模块导出的顶层方法。
-
var express = require('express');
-
var app = express();
中间件
http://expressjs.com/en/guide/using-middleware.html (参考文献)
express是一个路由和中间件Web框架,其自身的功能很少:Express应用程序本质上是一系列中间件函数调用。
中间件功能是可以访问请求对象(req
),响应对象(res
)和应用程序的请求-响应周期中的下一个中间件功能的功能。下一个中间件功能通常由名为的变量表示next
。
中间件功能可以执行以下任务:
- 执行任何代码。
- 更改请求和响应对象。
- 结束请求-响应周期。
- 调用堆栈中的下一个中间件函数。
如果当前的中间件功能没有结束请求-响应周期,则必须调用next()
将控制权传递给下一个中间件功能。否则,该请求将被挂起。
app.use()可以给所有的路由绑定一个中间件
不能给前端(send / sendFile / end /…)多次
Express应用程序可以使用以下类型的中间件:
您可以使用可选的安装路径加载应用程序级和路由器级中间件。您还可以将一系列中间件功能一起加载,这将在安装点创建中间件系统的子堆栈。
应用层中间件
使用和函数将应用程序级中间件绑定到应用程序对象的实例,其中,中间件函数处理的请求的HTTP方法(小写)是HTTP方法。app.use()``app.METHOD()``METHOD
此示例显示了没有安装路径的中间件功能。每次应用收到请求时,都会执行该功能。
var express = require('express')
var app = express()
app.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
})
此示例显示了/user/:id
路径上安装的中间件功能。该函数针对/user/:id
路径上的任何类型的HTTP请求执行。
app.use('/user/:id', function (req, res, next) {
console.log('Request Type:', req.method)
next()
})
此示例显示了路由及其处理程序功能(中间件系统)。该函数处理对/user/:id
路径的GET请求。
app.get('/user/:id', function (req, res, next) {
res.send('USER')
})
这是在具有安装路径的安装点加载一系列中间件功能的示例。它说明了一个中间件子栈,该子栈将任何类型的HTTP请求的请求信息打印到/user/:id
路径。
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()
})
路由处理程序使您可以为一个路径定义多个路由。下面的示例为到达/user/:id
路径的GET请求定义了两条路由。第二条路由不会引起任何问题,但是它永远不会被调用,因为第一条路由会结束请求-响应周期。
此示例显示了一个中间件子堆栈,该子堆栈处理对/user/:id
路径的GET请求。
app.get('/user/:id', function (req, res, next) {
console.log('ID:', req.params.id)
next()
}, function (req, res, next) {
res.send('User Info')
})
// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', function (req, res, next) {
res.end(req.params.id)
})
要从路由器中间件堆栈中跳过其余中间件功能,请调用next('route')
将控制权传递给下一条路由。 注意:next('route')
仅适用于使用app.METHOD()
或router.METHOD()
函数加载的中间件函数。
此示例显示了一个中间件子堆栈,该子堆栈处理对/user/:id
路径的GET请求。
app.get('/user/:id', function (req, res, next) {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route')
// otherwise pass the control to the next middleware function in this stack
else next()
}, function (req, res, next) {
// send a regular response
res.send('regular')
})
// handler for the /user/:id path, which sends a special response
app.get('/user/:id', function (req, res, next) {
res.send('special')
})
中间件也可以在数组中声明为可重用。
此示例显示了一个带有中间件子堆栈的数组,该子堆栈处理对/user/:id
路径的GET请求
function logOriginalUrl (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}
function logMethod (req, res, next) {
console.log('Request Type:', req.method)
next()
}
var logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, function (req, res, next) {
res.send('User Info')
})
路由器级中间件
路由器级中间件与应用程序级中间件的工作方式相同,只不过它绑定到的实例express.Router()
。
var router = express.Router()
使用router.use()
和router.METHOD()
函数加载路由器级中间件。
以下示例代码通过使用路由器级中间件来复制上面显示的用于应用程序级中间件的中间件系统:
var express = require('express')
var app = express()
var router = express.Router()
// a middleware function with no mount path. This code is executed for every request to the router
router.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
})
// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
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()
})
// a middleware sub-stack that handles GET requests to the /user/:id path
router.get('/user/:id', function (req, res, next) {
// if the user ID is 0, skip to the next router
if (req.params.id === '0') next('route')
// otherwise pass control to the next middleware function in this stack
else next()
}, function (req, res, next) {
// render a regular page
res.render('regular')
})
// handler for the /user/:id path, which renders a special page
router.get('/user/:id', function (req, res, next) {
console.log(req.params.id)
res.render('special')
})
// mount the router on the app
app.use('/', router)
要跳过路由器的其余中间件功能,请调用next('router')
将控制权转回路由器实例。
此示例显示了一个中间件子堆栈,该子堆栈处理对/user/:id
路径的GET请求。
var express = require('express')
var app = express()
var router = express.Router()
// predicate the router with a check and bail out when needed
router.use(function (req, res, next) {
if (!req.headers['x-auth']) return next('router')
next()
})
router.get('/user/:id', function (req, res) {
res.send('hello, user!')
})
// use the router and 401 anything falling through
app.use('/admin', router, function (req, res) {
res.sendStatus(401)
})
错误处理中间件
错误处理中间件始终采用四个参数。您必须提供四个参数以将其标识为错误处理中间件函数。即使您不需要使用该next
对象,也必须指定它以维护签名。否则,该next
对象将被解释为常规中间件,并且将无法处理错误。
以与其他中间件函数相同的方式定义错误处理中间件函数,除了使用四个参数而不是三个参数外,特别是使用签名(err, req, res, next)
):
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
有关错误处理中间件的详细信息,请参见:错误处理。
内置中间件
从版本4.x开始,Express不再依赖Connect。Express以前包含的中间件功能现在位于单独的模块中;请参阅中间件功能列表。
Express具有以下内置的中间件功能:
- express.static提供静态资产,例如HTML文件,图像等。
- express.json使用JSON负载解析传入的请求。注意:Express 4.16.0+中可用
- express.urlencoded使用URL编码的有效内容解析传入的请求。注意:Express 4.16.0+中可用
第三方中间件
使用第三方中间件向Express应用程序添加功能。
安装Node.js模块以获得所需的功能,然后在应用程序级别或路由器级别将其加载到您的应用程序中。
以下示例说明了如何安装和加载cookie解析中间件功能cookie-parser
。
$ npm install cookie-parser
var express = require('express')
var app = express()
var cookieParser = require('cookie-parser')
// load the cookie-parsing middleware
app.use(cookieParser())
数据的处理
index02.js
const express = require("express");
const path = require("path");
const app = express();
app.listen(7878);
/*使用中间件提前处理所有请求发送过来的数据
* 这个中间件不需要自己写express已经写好了,不需要我们自己再写任何东西,next等等都已经再内容写好了,照抄就可以了
* */
app.use(express.json());//内置中间件
app.use(express.urlencoded({extended:true}));//内置中间件
app.get("/",(req,res,next)=>{
console.log(req.query);/*这是GET发送的数据拿取方式*/
next();
});
app.get("/",(req,res)=>{
res.sendFile(path.join(__dirname,"./test.html"));
});
app.post("/",(req,res)=>{
console.log(req.body);/*这是POST发送的数据拿取方式*/
res.send({
code : 0,
msg : "请求已受理",
data : {
aaa : "这是后端给你的数据,拿好了!!"
}
});
});
/*
* 处理数据的中间件:
* app.use(express.json());
* app.use(express.urlencoded({extended:true}));
*
*
* 如何拿取前端发送过来的数据
* GET方式 req.query
* POST方式 req.body
*
*
* */
处理数据的中间件:
-
app.use(express.json());
-
app.use(express.urlencoded({extended:true}));
如何拿取前端发送过来的数据
-
GET方式 req.query
-
POST方式 req.body
test.html
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="按钮" id="btn">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script>
$("#btn").click(function(){
$.ajax({
type : "POST",
url : "/",
data : {name:"afei",age:18},
success(msg){
console.log(msg);
}
});
});
</script>
</body>
</html>
get方式加数据
localhost:7878?a=10&b=60&c=100
模块化问题
解决中间件函数过多造成的麻烦,使其模块化
app.js
const express = require("express");
let app = express();
app.listen(4567);
app.use(express.json());
app.use(express.urlencoded({extended:true}));
app.get("/",require("./middleware/index"));
app.post("/",require("./middleware/indexPOST"));
app.get("/article",require("./middleware/article"));
app.get("/favicon.ico",require("./middleware/favicon"));
article.js
module.exports = (req,res)=>{
res.send("这是article路由");
};
favicon.js
const path = require("path");
module.exports = (req,res)=>{
res.sendFile( path.join(__dirname,"../icon.png") );
};
index.js
const path = require("path");
module.exports = (req,res)=>{
res.sendFile( path.join(__dirname,"../test.html") );
};
indexPOST.js
module.exports = (req,res)=>{
console.log(req.body);/*这是POST发送的数据拿取方式*/
res.send({
code : 0,
msg : "请求已受理",
data : {
aaa : "这是后端给你的数据,拿好了!!"
}
});
};
如果出现如下错误:
get http://localhost:4567/favicon.ico 404(Not Found)
解决方法:
const path = require("path");
module.exports = (req,res)=>{
res.sendFile( path.join(__dirname,"../icon.png") );
};
app.get("/favicon.ico",require("./middleware/favicon"));
路由
http://expressjs.com/en/guide/routing.html (参考文献)
子路由
案例:
app设置teacher子路由
teacher又设置afei子路由
app.js
const express = require("express");
let app = express();
app.listen(7894);
/*用 use 才能使用子路由*/
app.use("/teacher",require("./routers/teacher"));
app.use("/a/b/c/d/e/f",(req,res)=>{
if (req.method === "GET") {
res.send("这是正确的,访问到了/a/b/c/d/e/f");
}else if (req.method === "POST"){
res.send("请使用get");
}
});
app.use((req,res)=>{
res.send("这是404页面");
});
/*
* 中间件函数
* next()
* app.use
* res.send() 不能重复
*
* 模块化代码
*
* express.Router()
*
*
*
* */
teacher.js
const express = require("express");
let router = express.Router();
router.get("/",(req,res)=>{
res.send("这是老师展示页");
});
router.use("/afei",require("./afei"));
router.get("/wulv",(req,res)=>{
res.send("无虑");
});
router.get("/yinshi",(req,res)=>{
res.send("银时");
});
router.get("/Sherry",(req,res)=>{
res.send("希尔瑞");
});
router.get("/kaidi",(req,res)=>{
res.send("凯迪");
});
module.exports = router;
afei.js
const express = require("express");
let router = express.Router();
router.get("/",(req,res)=>{
res.send("这是阿飞老师的主页");
});
router.get("/name",(req,res)=>{
res.send("阿飞");
});
router.get("/age",(req,res)=>{
res.send("18");
});
router.get("/sex",(req,res)=>{
res.send("男");
});
module.exports = router;