目录
一、什么是express?
基于Node.js运行环境的Web应用程序开发框架,express提供一个轻量级模块,将node.js的HTTP模块功能封装在一个简单易用的接口中,用于扩展HTTP模块的功能,能够轻松地处理服务器地路由、响应、cookie和HTTP请求的状态。
二、express优点?
1.简洁的路由定义方式
通过express.Router()方法定义路由对象,并实现二级路由功能。
2.简化HTTP请求参数的处理
express将HTTP参数转换成对象类型,通过请求对象的相关属性来获取请求参数,不需要为请求对象添加data事件以及对请求参数的格式进行处理。
3.提供中间件机制控制HTTP请求
中间件相当于express为用户提供了处理请求的接口,用于对HTTP请求进行拦截,能够让开发人员对请求进行控制。
4.拥有大量第三方中间件,少代码完成强功能
5.支持多种模板引擎
三、express使用步骤
- 引入express模块
- 调用express()方法创建Web服务器对象app
- 调用app.get()方法定义GET路由
- 调用app.listen()方法监听端口
//引入express模块
const express = require('express');
//创建web服务器对象
const app = express();
//定义GET路由
app.get('/', (req,res) => {
//对客户端做出响应,send()方法会根据内容的类型自动设置请求投
//第一个参数为请求路径,第二个参数标识请求处理函数,参数为req请求对象和res响应对象
res.send('hello word');
})
// 监听3000端口
app.listen(3000);
console.log("服务器启动成功");
四、express中间件
1. 什么是中间件?
express通过中间件来接收客户端发来的请求,并对请求做出响应,也可以将请求交给下一个中间件继续处理。工作流程如下:
2. 中间件应用场景
1.路由保护
当客户端访问登录页面是,可以先使用中间件判断用户的登陆状态,如果未登录,则拦截请求,直接响应提示信息,并禁止用户跳转到登陆页面。
2.网站维护公告
在所有路由最上面定义接收所有请求的中间件,直接为客户端做出响应,并提示网站正在维护中。
3.自定义404页面
在所有路由最上面定义接收所有请求的中间件,直接为客户端做出响应,提示404页面错误信息。
3. 如何定义中间件
中间件组成
- 中间件方法:由express提供,负责拦截请求
- 请求处理函数:由开发人员编写,负责处理请求
- 通过app.get()定义中间件
const express = require('express');
const app = express();
app.get('/request', (req,res,next) => {
//next参数是一个函数,标识当前请求处理完成后交给下一个中间件进行处理,
//如果后面没有其他中间件了,则交给路由返回最终结果
req.name = '张三';
//调用next()函数
next();
})
app.get('/request', (req,res) => {
res.send(req.name);
});
app.listen(4000);
console.log("服务器启动成功");
- 通过app.post()定义中间件
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="http://localhost:4000/post" method="post" style="width:245px">
<!-- method标签默认为get -->
<input type="submit" value="发送post请求">
</form>
</body>
</html>
post.js
onst express = require('express');
const app = express();
app.post('/post', (req, res, next) => {
req.name = '李四';
next();
});
app.post('/post', (req, res) => {
res.send(req.name);
})
app.listen(4000);
console.log("服务器已启动");
- 通过app.use()定义中间件
- app.use()定义的中间件既可以处理POST请求又可以处理GET请求。
- app.use()方法的请求路径参数可以省略,省略是表示不指定路径,所有请求都会处理。
- app.use()可以接收请求处理函数,也可以接收作为返回值的请求处理函数。
const express = require('express');
const app = express();
app.use((req, res, next) => {
req.user = {};
next();
});
// app.post('/use',(req, res, next) => {
// req.user.age = '24';
// next();
// });
// app.post('/use',(req,res) => {
// res.send(req.user.age);
// })
app.get('/use',(req, res,next) => {
req.user.name = '张三';
next();
})
app.get('/use',(req,res) => {
res.send(req.user.name);
})
app.listen(4000);
console.log("服务器已开启");
app.use()接收函数调用
const express = require('express');
const app = express();
app.use(fn( {a:1} ));
function fn(obj) {//obj接收参数对象
//请求处理函数作为返回值
return function(req, res, next) {
if ( obj.a === 1 ) {
console.log(req.url);
}else {
console.log(req.method);
};
next();
}
}
app.get('/use',(req,res) => {
res.send('ok');
})
app.listen(4000);
console.log("服务器已开启");
4. 利用中间件处理静态资源
express.static(),接收静态资源访问目录作为参数,是静态资源请求就直接响应给客户端,终止当前请求,否则调用next()函数,express.static()需要作为app.use()参数使用。
const express = require('express');
const express = require('express');
const app = express();
//public/images下存放图片
//public下新建html文件也可实现通过浏览器访问静态html页面
//访问http://localhost:3000/images/2.png
//访问http://localhost:3000/index.html
app.use(express.static("public"));
//单引号出错,双引号正常
app.listen(3000);
console.log("服务器已开启");
5. 利用中间件处理错误
App.use()请求处理函数多了一个err参数,添加err参数就表示利用中间件来处理错误。
const express = require('express');
//导入文件系统模块fs
const fs = require('fs');
const app = express();
app.get('/request', (req,res,next) => {
//读取文件函数
fs.readFile('./a.txt', 'utf8', (err,result) => {
//回调函数,err表示文件读取错误信息,result表示文件数据
if ( err !== null ){
next(err);
}else {
res.send(result);
}
})
});
app.use((err,req,res,next) => {
res.status(500).send(err.message);
});
app.listen(3000);
console.log("服务器已开启");
node.js中fs模块可使用同步方法和异步方法。异步方法性能更好,速度更快,且没有阻塞。
同步方法:fs.readFileSync(filename,encoding),
异步方法:fs.readFile(filename,encoding,[callback(err,data)]),最后一个参数是回调函数,包含错误信息err和文件内容data。
6. 利用中间件处捕获异步函数错误
异步函数以及其他同步代码在执行过程中发生的错误,使用try...catch语法结合async和await关键字实现。
const express = require('express');
const fs = require('fs');
//为了使fs.readFile支持async,await异步函数调用方式,需要借助promisify模块实现
//导入util模块,并将promisify属性的值赋值给promisify常量
const promisify = require('util').promisify;
//调用promisify()方法,并将fs.readFile传入
const readFile = promisify(fs.readFile);
const app = express();
// 定义async中间件,async关键字定义异步回调函数
app.get('/async', async(req, res, next) => {
try {
await readFile('./aaa.txt');
}catch(err) {
next(err);
}
});
app.listen(3000);
console.log("服务器已开启");
五、express模块化路由
为了方便多种类路由管理,使用express.Router()进行路由管理,可以将同一类路由放在一个单独的文件夹,每个单独的文件表示一个单独的模块,通过文件名称来区分路由的功能。
//route文件夹下home.js
const express = require('express');
const home = express.Router();
home.get('/index',(req,res) => {
res.send('欢迎来到主页');
});
module.exports = home;
//module.js
const express = require('express');
const home = require('./route/home.js');
const app = express();
app.use('/home',home);
app.listen(3000);
console.log("服务器已开启");
六、express接收请求参数
-
接收GET请求参数
express框架中的req.query用于获取GET请求参数,框架内部会将GET请求参数转化为对象并返回。
//route文件夹下admin.js
const express = require('express');
const admin = express.Router();
admin.get('/index',(req,res) => {
res.send(req.query);
});
module.exports = admin;
//module.js
const express = require('express');
const app = express();
const admin = require('./route/admin.js');
app.use('/admin',admin);
app.listen(3000);
console.log("服务器已开启");
2. 接收POST请求参数
express中req.body用于获取POST请求参数,需要借助第三方bodu-parser模块将POST参数转换成对象形式。POST请求参数于GET请求参数不同之处在于,POST请求参数不会再浏览器地址栏中显示。
// module.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({extended:false}));
app.post('/body',(req,res) => {
res.send(req.body);
});
app.listen(3000);
console.log("服务器已开启");
<form action="http://localhost:3000/body" method="post" style="width: 245px">
用户名: <input type="text" style="float:right" name="username" /><br><br>
密码: <input type="password" style="float:right" name="password" /><br><br>
<input type="submit" value="提交">
</form>
3. 接收路由请求参数
定义路由时,可以在请求路径中传递路由参数,使用req.params获取参数,使路由代码看起来美观,且请求参数会被清晰地展示出来。
const express = require('express');
const app = express();
//":id"是一个参数占位符,当浏览器向"/find/:id"地址发送请求时,":id"对应的值就是参数值
app.get('/find/:id/:name/:age',(req,res) => {
res.send(req.params);
});
app.listen(3000);
console.log("服务器已开启");