一. express 简介
express官网https://www.expressjs.com.cn/
基于Node.js
平台,快速、开放、极简的Web
开发框架
安装:
npm install express --save
使用express
可以方便快速的创建web
网站的服务器或者api
接口的服务器
1. 使用express创建基本的服务器
// 1.导入express
const express = require('express')
// 2.创建web服务器
const app = express()
// 3.启动服务器
app.listen(80, ()=>{
console.log('express服务器启动成功,http://127.0.0.1:80')
})
2. 监听get/post请求
// 参数1:客户端请求的url地址
// 参数2:请求对应的处理函数 (req请求对象,res响应对象)
app.get('请求url', function(req, res) {'处理函数'})
app.post('请求url', function(req, res) {'处理函数'})
3. 把内容响应给客户端
通过res.send()方法把内容响应给客户端
app.get('/user', (req, res) => {
//向客户端发送JSON对象
res.send({name: 'zhangsan', age: '18'})
})
示例:
// 1.导入express
const express = require("express");
// 2.创建web服务器
const app = express();
// 4. 监听客户端的 GET 和 POST 请求,并向客户端响应具体的内容
app.get("/user", (req, res) => {
// 调用 express 提供的 res.send() 方法,向客户端响应一个 JSON 对象
res.send({ name: "zs", age: 20, gender: "男" });
});
app.post("/user", (req, res) => {
// 调用 express 提供的 res.send() 方法,向客户端响应一个 文本字符串
res.send("请求成功");
});
// 3.启动服务器
app.listen(80, () => {
console.log("express服务器启动成功,http://127.0.0.1:80");
});
此时启动一下该服务器:
node 文件名.js
当你看到这一句话时代表你的服务器创建成功了
接着我们可以使用postman测试一下这两个接口
get
post
4. 通过req.query可以获取到客户端发过来的查询参数
// 1. 导入 express
const express = require('express')
// 2. 创建 web 服务器
const app = express()
app.get('/', (req, res) => {
// 通过 req.query 可以获取到客户端发送过来的 查询参数
// 注意:默认情况下,req.query 是一个空对象
console.log(req.query)
res.send(req.query)
})
// 3. 启动 web 服务器
app.listen(80, () => {
console.log('express server running at http://127.0.0.1')
})
运行然后去postman测试
可以看到此处响应了一个空对象,可以证明req.query默认就是一个空对象
接着我们携带一些参数发送请求:
5. 获取url中的动态参数
通过req.params
对象,可以访问到url中通过:匹配到的动态参数
// 1.导入express
const express = require("express");
// 2.创建web服务器
const app = express();
// 注意:这里的 :id 是一个动态的参数
app.get("/user/:ids/:username", (req, res) => {
// req.params 是动态匹配到的 URL 参数,默认也是一个空对象
console.log(req.params);
res.send(req.params);
});
// 3.启动服务器
app.listen(80, () => {
console.log("express服务器启动成功,http://127.0.0.1:80");
});
6. 托管静态资源
express.static()
通过express.static
可以创建一个静态资源服务器
,如下代码,就可以将public
目录下的图片、css文件、javascript文件对外开放
app.use(express.static(‘public’))
现在就可以访问public
目录下的所有文件了
http://localhost:80/images/bg.jpg
http://localhost:80/css/stylse.css
挂载路径前缀
app.use(‘/files’, express.static(‘files’))
挂载前缀之后我们要访问的静态资源路径就变为了如下:
http://localhost:80/files/index.html
7. nodemon
nodemon
是一个工具,在我们编写node项目时,如果修改了代码,就得频繁的手动关闭重启项目,nodemon它可以监听项目的文件变动
,然后自动帮我们重启项目,极大的方便了我们的开发和调试。
启动命令
nodemon 监听文件名.js
二. express 路由
1.概念
路由就是映射关系,在express中路由指的是客户端的请求与服务器之间的映射关系。
express中路由分3部分组成,分别是请求的类型、请求的url、处理函数,格式如下:
app.method(path, handler)
app.get('/', function(req, res){
res.send('hello express')
})
2.模块化路由
为了方便对路由进行模块化管理,Express不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块,步骤如下:
- 创建路由对应的js文件
- 调用express.Router()函数创建路由对象
- 向路由对象上挂载具体的路由
- 使用module.exports向外共享路由对象
- 使用app.use()函数注册路由模块
示例如下:
// 这是路由模块 router.js
// 1. 导入 express
const express = require('express')
// 2. 创建路由对象
const router = express.Router()
// 3. 挂载具体的路由
router.get('/user/list', (req, res) => {
res.send('Get user list.')
})
router.post('/user/add', (req, res) => {
res.send('Add new user.')
})
// 4. 向外导出路由对象
module.exports = router
在app.js中注册使用
const express = require('express')
const app = express()
// app.use('/files', express.static('./files'))
// 1. 导入路由模块
const router = require('./router')
// 2. 注册路由模块
app.use('/api', router)
// 注意: app.use() 函数的作用,就是来注册全局中间件
app.listen(80, () => {
console.log('http://127.0.0.1')
})
三. 中间件
1. 概念
中间件,特指业务流程的中间处理环节
express中间件,本质上就是一个function处理函数,Express中间件的格式如下:
app.get('/', function(req, res, next) => {
next()
})
中间件函数的形参列表中,必须包含next参数,而路由处理函数中只包含req和res。
next()
函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。
2.全局生效的中间件
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件,通过调用app.use(中间件函数),即可定义一个全局生效的中间件,如下:
const express = require('express')
const app = express()
// // 定义一个最简单的中间件函数
// const mw = function (req, res, next) {
// console.log('这是最简单的中间件函数')
// // 把流转关系,转交给下一个中间件或路由
// next()
// }
// // 将 mw 注册为全局生效的中间件
// app.use(mw)
// 这是定义全局中间件的简化形式
app.use((req, res, next) => {
console.log('这是最简单的中间件函数')
next()
})
app.get('/', (req, res) => {
console.log('调用了 / 这个路由')
res.send('Home page.')
})
app.get('/user', (req, res) => {
console.log('调用了 /user 这个路由')
res.send('User page.')
})
app.listen(80, () => {
console.log('http://127.0.0.1')
})
接着我们启动这个服务,用postman调用接口看看我们定义的中间件是否生效
如上图,接口调用成功,控制台先打印了中间的内容,在打印接口的内容,说明我们定义的中间件生效了。
3.中间件的作用
多个中间件之间共享同一份req
和res
,基于这样的特性,我们可以在上游的中间件中,统一为req
或res
对象添加自定义的属性和方法
,供下面的中间件或者路由使用。
const express = require('express')
const app = express()
// 这是定义全局中间件的简化形式
app.use((req, res, next) => {
// 获取到请求到达服务器的时间
const time = Date.now()
// 为 req 对象,挂载自定义属性,从而把时间共享给后面的所有路由
req.startTime = time
next()
})
app.get('/', (req, res) => {
res.send('Home page.' + req.startTime)
})
app.get('/user', (req, res) => {
res.send('User page.' + req.startTime)
})
app.listen(80, () => {
console.log('http://127.0.0.1')
})
4.定义多个全局中间件
const express = require('express')
const app = express()
// 定义第一个全局中间件
app.use((req, res, next) => {
console.log('调用了第1个全局中间件')
next()
})
// 定义第二个全局中间件
app.use((req, res, next) => {
console.log('调用了第2个全局中间件')
next()
})
// 定义一个路由
app.get('/user', (req, res) => {
res.send('User page.')
})
app.listen(80, () => {
console.log('http://127.0.0.1')
})
如上图所示,我们在调用接口之后,控制台依次输出了全局中间件内容。
5.局部生效的中间件
不使用app.use
定义的中间件,就叫做局部生效的中间件。如下示例:
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 1. 定义中间件函数
const mw1 = (req, res, next) => {
console.log('调用了局部生效的中间件')
next()
}
// 2. 创建路由
app.get('/', mw1, (req, res) => {
res.send('Home page.')
})
app.get('/user', (req, res) => {
res.send('User page.')
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
如上图我们调用’/user’接口时,控制台没有打印中间件中的内容
当我们调用‘/’时,控制台打印了中间的内容,说明局部的中间件生效了。
6.调用多个局部生效的中间件
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 1. 定义中间件函数
const mw1 = (req, res, next) => {
console.log('调用了第一个局部生效的中间件')
next()
}
const mw2 = (req, res, next) => {
console.log('调用了第二个局部生效的中间件')
next()
}
// 2. 创建路由
app.get('/', [mw1, mw2], (req, res) => {
res.send('Home page.')
})
app.get('/user', (req, res) => {
res.send('User page.')
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
7.中间件的分类
- 应用级别的中间件:绑定到app实例上的中间件如:app.use(), app.get()
- 路由级别的中间件:绑定到express.Router()实例上的中间件
- 错误级别的中间件
- express内置的中间件
- 第三方的中间件
8.错误级别中间件
作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。
注意:错误级别中间件要放在路由之后
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 1. 定义路由
app.get('/', (req, res) => {
// 1.1 人为的制造错误
throw new Error('服务器内部发生了错误!')
res.send('Home page.')
})
// 2. 定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的崩溃
app.use((err, req, res, next) => {
console.log('发生了错误!' + err.message)
res.send('Error:' + err.message)
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
9.常用的内置中间件
- express.static() 快速托管静态资源
- express.json() 解析json格式请求体数据
- express.urlencoded解析URL-encoded格式的请求体数据。
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 注意:除了错误级别的中间件,其他的中间件,必须在路由之前进行配置
// 通过 express.json() 这个中间件,解析表单中的 JSON 格式的数据
app.use(express.json())
// 通过 express.urlencoded() 这个中间件,来解析 表单中的 url-encoded 格式的数据
app.use(express.urlencoded({ extended: false }))
app.post('/user', (req, res) => {
// 在服务器,可以使用 req.body 这个属性,来接收客户端发送过来的请求体数据
// 默认情况下,如果不配置解析表单数据的中间件,则 req.body 默认等于 undefined
console.log(req.body)
res.send('ok')
})
app.post('/book', (req, res) => {
// 在服务器端,可以通过 req.body 来获取 JSON 格式的表单数据和 url-encoded 格式的数据
console.log(req.body)
res.send('ok')
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
10. 第三方中间件
body-parser中间件,用来解析表单数据
使用步骤
- 安装:
npm i body-parser
- 导入:
const parser = require('body-parser')
- 使用:
app.use(parser.urlencoded({extend: false}))
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 1. 导入解析表单数据的中间件 body-parser
const parser = require('body-parser')
// 2. 使用 app.use() 注册中间件
app.use(parser.urlencoded({ extended: false }))
// app.use(express.urlencoded({ extended: false }))
app.post('/user', (req, res) => {
// 如果没有配置任何解析表单数据的中间件,则 req.body 默认等于 undefined
console.log(req.body)
res.send('ok')
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
11 自定义解析表单数据中间件
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 导入 Node.js 内置的 querystring 模块
const qs = require('querystring')
// 这是解析表单数据的中间件
app.use((req, res, next) => {
// 定义中间件具体的业务逻辑
// 1. 定义一个 str 字符串,专门用来存储客户端发送过来的请求体数据
let str = ''
// 2. 监听 req 的 data 事件
req.on('data', (chunk) => {
str += chunk
})
// 3. 监听 req 的 end 事件
req.on('end', () => {
// 在 str 中存放的是完整的请求体数据
// console.log(str)
// TODO: 把字符串格式的请求体数据,解析成对象格式
const body = qs.parse(str)
req.body = body
next()
})
})
app.post('/user', (req, res) => {
res.send(req.body)
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})