一、介绍
-
官方概念:Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架。
-
Express 是第三方的 npm 包。
-
http 内置模块复杂,开发效率低。Express 是基于内置的http模块进一步封装,能够极大的提高开发效率。(类似于浏览器中 Web API 和 jQuery 的关系。后者是基于前者进一步封装出来的)
Web 网站服务器:对外提供 Web 网页资源的服务器。
API 接口服务器:对外提供 API 接口的服务器。
使用 Express,可以方便、快速的创建 Web 网站服务器或 API 接口服务器。
二、初识 Express
1、安装
在项目所属目录,安装 npm i express@4.17.1
2、创建基本的Web服务器
// 1. 导入 express
const express = require('express')
// 2. 创建 web 服务器
const app = express()
// 3. 启动 web 服务器
app.listen(80, () => {
// 端口号是80则路径可省略不写80
console.log('express server running at http://127.0.0.1')
})
3、监听 GET 和 POST 请求 & 处理参数
(1)监听 GET 请求
通过 app.get() 方法
// req:请求对象
// res:响应对象
app.get('请求的URL', function(req, res) { /* 处理函数 */ })
(2)监听 POST 请求
通过 app.post() 方法
// req:请求对象
// res:响应对象
app.post('请求的URL', function(req, res) { /* 处理函数 */ })
(3)把内容响应给客户端
通过 res.send() 方法,把处理好的内容,发送给客户端
app.get('/user', (req, res) => {
res.send({ name: 'liming', sex: '男' })
})
app.post('/user', (req, res) => {
res.send('请求成功')
})
然后在 postman 输入 http://127.0.0.1/user 测试即可。
(4)获取 URL 携带的查询参数
通过 req.query
可以获取到客户端通过查询字符串
的形式,发送到服务器的参数
app.get('/user', (req, res) => {
// 通过 req.query 可以获取到 客户端发来的查询参数
// 默认 req.query 是个空对象
// 地址 http://127.0.0.1/?name=liming&age=20
res.send(req.query.name); // liming
}
(5)获取 URL 携带的动态参数
通过req.params
对象,可以访问到URL中,通过:
匹配到的动态参数:
// 这里的 :id 是个动态参数
app.get("/user/:id", (req, res) => {
// 通过 req.params 可以获取到 通过 : 匹配到的动态参数
// 默认 req.params 是个空对象
// 地址 http://127.0.0.1/user/3
res.send(req.params.id); // 3
});
4、静态资源处理
- express.static()
通过express.static()
,可以非常方便地创建一个静态资源服务器。
例:
将 public
目录下的图片等对外开放访问。
app.use(express.static('public'))
通过以下访问静态资源:
localhost/images/1.jpg
localhost/css/style.css
(注:存放静态文件的目录名(此例的 public)不会出现在URL中)
- 托管多个静态资源目录:
多次调用 express.static()
app.use(express.static('public'))
app.use(express.static('files'))
根据目录的添加顺序 查找所需文件。若找到相应文件,则不会在下个目录找。
- 挂载路径前缀
app.use('/public', express.static('public'))
通过带有 public
的前缀地址 访问 public
目录的文件
localhost/public/images/1.jpg
localhost/public/css/style.css
5、使用 nodemon 监听并自动重启项目
修改了node 项目的代码,需要频繁的手动重新启动项目。
为了方便,我们使用 nodemon (https://www.npmjs.com/package/nodemon) 工具,能够监听项目文件的变动,当代码被修改后,nodemon会自动重启项目,方便开发和调试。
三、Express 的路由
理解:路由就是映射关系。
Express 中,路由指 客户端的请求与服务器处理函数 之间的映射关系。
Express 中的路由,为3部分组成,分别是请求的类型、请求的URL地址、处理函数。
每当一个请求到达服务器后,先经过路由的匹配,只有匹配成功后,才会调用对应的处理函数。
在匹配时,会按照路由定义的先后顺序进行匹配,如果请求类型和请求的URL同时匹配成功,则Express 会将这次请求,转交给对应的 function 函数进行处理。
1、简单写法
app.get('/user', (req, res) => {
res.send({ name: 'liming', sex: '男' })
})
app.post('/user', (req, res) => {
res.send('请求成功')
})
当然后期不会用此写法,因为路由多的情况下,会产生很多行代码,且不好维护。
2、模块化路由
为了方便,对路由进行模块化管理。最好不将路由直接挂载在 app 上,而是将 路由抽离为单独的模块。
-
创建路由模块的 js 文件
创建 router/user.js
//1. 导入 express
const express = require('express')
// 2. 创建路由对象
const router = express.Router()
// 3. 挂载具体的路由
router.get('/user/info', (req, res) => {
res.send('男,20岁')
})
router.post('/user/save', (req, res) => {
res.send('保存成功')
})
// 4. 暴露路由对象
module.exports = router
- 注册路由模块
const express = require('express')
const app = express()
// 1. 导入路由模块
const userRouter = require('./router/user.js')
// 2. 注册路由模块
app.use(userRouter)
app.listen(80, () => {
console.log('http://127.0.0.1')
})
注:上述我们用到 app.use(express.static('./public'))
托管静态资源 和 app.use(userRouter)
注册路由模块。所以:app.use()
的作用,是注册全局中间件。(关于中间件,下面会讲到)
- 为路由模块添加前缀
// 2. 注册路由模块并添加统一访问前缀
app.use('/api', userRouter)
访问路径需加上 /api
,如:
localhost/api/user/info
四、Express 中间件
1、中间件的概念
中间件(Middleware), 特指业务流程的中间处理环节。
(就像污水经过三层处理流程,才从起初的污水 变为 处理过的水。)
(1)Express 中间件的调用流程
当一个请求到达 Express 的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。
Express的中间件,本质是一个function处理函数,Express 中间件的格式如下:
app.get('/', function(req, res, next) {
next();
})
注:中间件函数的形参列表中,必须包含 next
参数。而路由处理函数中只包含req
和res
。
(2)next
函数的作用
next
函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。
2、Express 中间件初体验
(1)定义中间件函数
// mw 是中间件缩写
const mw = function (req, res, next) {
console.log('这是一个简单的中间件函数')
// 注:在当前中间件的业务处理完毕后,必须调用next()函数,把流转关系转交给下一个中间件或路由
next()
}
(2)全局生效的中间件
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。
通过调用app.use(中间件函数)
,即可定义一个全局生效的中间件, 如下:
// 定义中间件函数, mw 是中间件缩写
const mw = function (req, res, next) {
console.log('这是一个简单的中间件函数')
// 注:在当前中间件的业务处理完毕后,必须调用next()函数,把流转关系转交给下一个中间件或路由
next()
}
// 将 mw 注册为全局生效的中间件
app.use(mw)
app.get('/user', (req, res) => {
console.log('调用了 /user 这个路由')
res.send('get a get')
})
当 url 为 http://localhost/user :先经 mw 中间件,再经 /user 路由
终端输出:
定义全局中间件的 简化形式:
app.use((req, res, next) => {
console.log('这是一个简单的中间件函数')
next()
})
(3)中间件的作用
多个中间件之间,共享同一份req
和res
。基于此特性,我们可以在上游的中间件中,统一为req
或res
对象添加自定义的属性或方法,供下游的中间件或路由进行使用。
app.use((req, res, next) => {
// 获取请求到达服务器的时间
const time = Date.Now()
// 为 req 对象 挂在自定义属性,从而把时间共享给后面所有的路由
req.startTime = time
next()
})
app.get('/user', (req, res) => {
res.send('get a get' + req.startTime)
})
(4)定义多个全局中间件
可以使用 app.use()
连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用
如下:
app.use((req, res, next) => {
req.aa = "先调用第一个全局中间件"
next()
})
app.use((req, res, next) => {
req.b= "后调用第二个全局中间件"
next()
})
(5)局部生效的中间件
不使用 app.use()
定义的中间件,叫做局部生效的中间件。
// 定义中间件函数
const mw1 = function (req, res, next) {
console.log('调用了局部中间件')
next()
}
// mw1中间件 作为app.get参数,只在当前路由/login生效
app.get('/login', mw1, (req, res) => {
res.send('get a login')
})
app.get('/user', (req, res) => {
res.send('get a user')
})
当 url 为 http://localhost/login 终端输出:调用了局部中间件
当 url 为 http://localhost/user 终端无输出
(6)定义多个局部中间件
// 按先后顺序依次进行调用局部中间件
// 以下两种写法等价
app.get('/login', mw1, mw2, (req, res) => { res.send('get a login') })
app.get('/login', [mw1, mw2], (req, res) => { res.send('get a login') })
(7)中间件的5个使用注意事项
- 必须在路由之前注册中间件
- 客户端发来的请求,可以连续调用多个中间件进行处理
- 执行完中间件的业务代码后,必须调用 next()
- 为了防止代码逻辑混乱,调用 next() 后不写额外代码
- 连续调用多个中间件时,多个中间件之间,共享 req 和 res 对象
3、中间件的分类
Express 官方把常见的中间件用法,分了5大类,分别是:
- 应用级别的中间件
- 路由级别的中间件
- 错误级别的中间件
- Express 内置的中间件
- 第三方的中间件
(1)应用级别的中间件
通过 app.use()
或 app.get()
或 app.post()
,绑定到app
实例上的中间件,叫做应用级别的中间件。
(2)路由级别的中间件
绑定到 express.Router()
实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别,区别是应用级别中间件是绑定到 app 实例上,路由级别中间件绑定到 router 实例上。
var app = express()
var router = express.Router()
// 路由级别的中间件
router.use((req, res, next) {
console.log('???')
next()
})
app.use('/', router)
(3)错误级别的中间件
错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。
格式: 错误级别中间件的 function 处理函数中,必须有4个形参,形参顺序从前到后,分别是(err, req, res, next)。
app.get('/', function (req, res) {
// 抛出一个自定义的错误(在这里模拟项目出错)
throw new Error('服务器内部发生了错误')
res.send('get a get') // 将不执行
})
// 定义错误级别的中间件,会捕获整个项目中发生的错误,防止项目异常崩溃
app.use(function (err, req, res, next) {
res.send('错误:' + err.message) // 客户端接收到:错误:服务器内部发生了错误
})
(4)Express 内置的中间件
自Express 4.16.0版本开始,Express 内置了 3个 常用的中间件,极大的提高了 Express 项目的开发效率和体验:
- express.static 快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS 样式等(无兼容性问题)(在前面讲到过)
- express.json 解析 JSON 格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
- express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,仅4.16.0+版本中可用)
// 配置解析 application/json 格式数据的内置中间件
app.use(express.json()
// 配置解析 application/x-www-form-urlencoded 格式数据的内置中间件
app.use(express.urlencoded({ extended: false }))
(5)第三方的中间件
原文地址:https://www.jb51.cc/wenti/3282875.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。