node.js学习笔记3 express基本使用、托管静态资源、express中间件

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服务器

// 导入express
const 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()),而是推荐将路由抽离为单独的模块
将路由抽离为单独模块的步骤:

  1. 创建路由模块对应的.js文件
  2. 调用express.Router()函数创建路由对象
  3. 向路由对象上挂载具体的路由
  4. 使用module.exports向外导出路由对象
// user.js
const 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 // 向外导出路由对象
  1. 使用app.use()函数注册路由模块
// main.js
const 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参数,而路由处理函数中只包含reqres

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默认等于undefined
  console.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 第三方的中间件

这个没什么要记的(๑•̀ㅂ•́)و✧


中间件真的有、、折磨 ╮(╯▽╰)╭

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值