内容
1. 什么是express1.1 http模块和express的关系2. express能做什么3. express的基本使用3.1 安装3.2 创建最基本的web服务器3.3 监听get请求3.4 监听post请求3.5 把内容响应给客户端3.6 获取url中携带的查询参数3.7 获取url中的动态参数4. 托管静态资源4.1 express.static()4.2 托管多个静态资源目录4.3 挂在路径前缀5. nodemon5.1 安装nodemon5.2 使用nodemon6. express路由6.1 模块化路由6.2 为路由模块添加前缀7. express中间件7.1 express中间件的调用流程7.2 express中间件的格式7.2.1 next函数的作用7.3 使用中间件7.3.1 定义中间件函数7.3.2 全局中间件7.3.3 局部中间件7.3.4 中间件分类7.3.4.1 应用级别的中间件7.3.4.2 路由级别的中间件7.3.4.3 错误级别的中间件7.3.4.4 express内置的中间件7.3.4.5 第三方的中间件1. 什么是express
express是基于Node.js平台,快速、开放、极简的Web开发框架
通俗的理解:express的作用和Node.js内置的http模块类似,是专门用来创建web服务器
的
1.1 http模块和express的关系
express是基于内置的http模块进一步封装出来的,能极大地提高开发效率
2. express能做什么
对于前端程序员,最常见的两种服务器,分别是:
web网站服务器
:专门向外提供web网页资源
的服务器api接口服务器
:专门向外提供api接口
的服务器
使用express,我们可以方便快捷地创建web网站的服务器或api接口的服务器
3. express的基本使用
3.1 安装
此处安装指定了版本
npm i express@4.17.1
3.2 创建最基本的web服务器
// 导入expressconst express = require('express')// 创建web服务器const app = express()// 启动服务器app.listen(80,() => {console.log('express server running at http://127.0.0.1');})
3.3 监听get请求
// req请求对象,res响应对象app.get('客户端的请求url',(req,res) => {/* 处理函数 */})
3.4 监听post请求
app.post('客户端的请求url',(req,res) => {/* 处理函数 */})
3.5 把内容响应给客户端
通过res.send()
方法,可以将处理好的内容,发送给客户端
app.get('/user',(req,res) => {// 向客户端响应一个JSON对象res.send({name: 'AIpoem', age: 20})})app.post('/user',(req,res) => {// 向客户端响应一个文本字符串res.send('请求成功')})
3.6 获取url中携带的查询参数
通过req.query
对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数:
app.get('/sendQuery',(req,res) => {// req.query默认是一个空对象// 客户端使用 ?name=AIpoem&age=20 这种查询字符串的形式,发送到服务器的参数// 可以通过req.query对象访问到res.send(req.query)})
3.7 获取url中的动态参数
通过req.params
对象,可以访问到url中,通过:
匹配到的动态参数:
// url中,可以通过 :参数名 的形式,匹配动态参数值app.get('/user/:id',(req,res) => {// req.params默认是一个空对象res.send(req.params)})
动态参数也不是只能有一个,可以设置多个
// url中,可以通过 :参数名 的形式,匹配动态参数值app.get('/user/:id/:name',(req,res) => {// req.params默认是一个空对象res.send(req.params)})
4. 托管静态资源
4.1 express.static()
通过express.static()
,我们可以非常方便地创建一个静态资源服务器
例如,通过以下代码就饿可以将public
目录下的图片、css文件、js文件对外开放访问
app.use(express.static('public'))
可以访问public目录中的所有文件了:
http://127.0.0.1/1.js
http://127.0.0.1/123.png
注意:存放静态资源文件的目录名不会出现在url中
4.2 托管多个静态资源目录
如果要托管多个静态资源目录,则多次调用express.static()
函数
app.use(express.static('public1'))app.use(express.static('public2'))
4.3 挂在路径前缀
如果希望在托管的静态资源访问路径
之前,挂载路径前缀,则可以使用以下方式:
app.use('/public',express.static('public'))
可以通过带有/public
前缀的地址来访问public目录中的所有文件了:
http://127.0.0.1/public/1.js
http://127.0.0.1/public/123.png
5. nodemon
编写调试Node.js项目时,如果修改了项目的代码,需要频繁地手动close掉然后再重新启动,使用nodemon这个工具,当代码被修改后,nodemon会自动重启项目
5.1 安装nodemon
npm i nodemon -g
5.2 使用nodemon
node app.js# 上面的终端命令替换成下面的终端命令nodemon app.js
6. express路由
在express中,路由指的是客户端的请求
和服务器处理函数
之间的映射关系
express中的路由由三部分组成,分别是请求类型
、请求url
、处理函数
例如:
// req请求对象,res响应对象app.get('客户端的请求url',(req,res) => {/* 处理函数 */})
当一个请求到达服务器后,需要先经过路由的匹配,匹配成功后才会调用对应的处理函数(如果请求类型和请求url同时匹配成功,则express会将这次请求转交给对应的函数处理
6.1 模块化路由
为了方便对路由进行模块化
管理,express不建议将路由直接挂载到app上(const app = express()
),而是推荐将路由抽离为单独的模块
将路由抽离为单独模块的步骤:
创建路由模块对应的.js
文件调用express.Router()
函数创建路由对象向路由对象上挂载具体的路由使用module.exports
向外导出路由对象
// user.jsconst express = require('express')const router = express.Router() // 创建路由对象router.get('/user/list',(req,res) => {// 向路由对象上挂载获取用户列表的路由res.send('get your list')})router.post('/user/add',(req,res) => {// 向路由对象上挂载添加用户的路由res.send('add new user')})module.exports = router // 向外导出路由对象
使用app.use()
函数注册路由模块
// main.jsconst userRouter = require('./user.js') // 导入路由模块app.use(userRouter) // 注册路由模块
⚠️:app.use()
函数的作用,就是来注册全局中间件
6.2 为路由模块添加前缀
路由模块添加前缀的方式和为静态资源挂载访问前缀是一样的
const userRouter = require('./user.js') // 导入路由模块app.use('/api',userRouter) // 注册路由模块
加了/api
前缀之后,发送请求的url就变成了http://127.0.0.1/api/user/list
7. express中间件
中间件,特指业务流程的中间处理环节
7.1 express中间件的调用流程
当一个请求到达express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理
7.2 express中间件的格式
express的中间件本质上就是一个处理函数,格式如下:
⚠️:中间件函数的形参列表中必须包含next参数
,而路由处理函数中只包含req
和res
7.2.1 next函数的作用
只要在某一个中间件中调用了next()
就表示处理完毕了,要将处理结果转交给下一个中间件或路由
7.3 使用中间件
7.3.1 定义中间件函数
const mw = (req,res,next) => {console.log('一个简单的中间件函数');// 当前中间件的业务处理完毕后,必须调用next()函数next();}
7.3.2 全局中间件
客户端发起的任何请求
,到达服务器之后,都会触发
的中间件,就是全局中间件
通过调用app.use(中间件函数)
,可以定义一个全局生效的中间件
const mw = (req,res,next) => {console.log('一个全局生效的中间件函数')// 当前中间件的业务处理完毕后,必须调用next()函数next()}// 将mw注册为全局生效的中间件app.use(mw)
定义全局中间件的简化形式:
app.use((req,res,next) => {console.log('一个全局生效的中间件函数')next()})
定义多个全局中间件:
还是使用app.use()
连续定义多个即可,客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用
7.3.3 局部中间件
不使用app.use()
定义的中间件
如:
const mw1 = (req,res,next) => {console.log('一个局部生效的中间件函数')next()}// mw1中间件只在当前路由中生效app.get('/home',mw1,(req,res) => {res.send('home page')})// mw1中间件不会影响此路由app.get('/user',(req,res) => {res.send('user page')})
定义多个局部中间件:
// 以下两种方式等价,顺序从左到右app.get('/home',mw1,mw2,mw3,(req,res) => {res.send('home page')})app.get('/home',[mw1,mw2,mw3],(req,res) => {res.send('home page')})
7.3.4 中间件分类
7.3.4.1 应用级别的中间件
通过app.use()
(全局)或app.get()
(局部)或app.post()
(局部)绑定到app实例上的中间件
7.3.4.2 路由级别的中间件
绑定到express.Router()
实例上的中间件
7.3.4.3 错误级别的中间件
专门用来捕获整个项目中发生的一场错误,从而防止项目异常崩溃的问题
错误级别中间件的处理函数中,必须有4个形参,分别是(err,req,res,next)
app.get('/',(req,res) => {// 人为的制造错误throw new Error('服务器内部发生了错误!')// 这行代码执行不了res.send('home page')})// throw error之后立即跳进错误级别中间件中,向客户端响应错误消息app.use((err,req,res,next) => {console.log('发生了错误' + err.message)res.send('Error:' + err.message)})
⚠️:错误级别的中间件必须注册在所有路由之后
7.3.4.4 express内置的中间件
express内置了3个常用的中间件
1.express.static
快速托管静态资源的内置中间件
2.express.json
解析JSON格式的请求体数据
// 配置解析 application/json 格式数据的内置中间件app.use(express.json())
3.express.urlencoded
解析URL-encoded格式的请求体数据
// 配置解析 application/x-www-form-urlencoded 格式数据的内置中间件app.use(express.urlencoded({extended: false }))
例:
app.post('/user',(req,res) => {// req.body接收客户端发送的请求体数据// 如果不配置解析表单数据的中间件,req.body默认等于undefinedconsole.log(req.body) // undefined})
在路由前配置好解析JSON格式请求体数据的中间件:
app.use(express.json())app.post('/user',(req,res) => {console.log(req.body) // { name: 'AIpoem', age: 20 }})
7.3.4.5 第三方的中间件
这个没什么要记的(๑•̀ㅂ•́)و✧
中间件真的有、、折磨 ╮(╯▽╰)╭