什么是 Express
Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架。
Express是对node核心模块http的封装跟拓展
Express 的基本使用
安装
创建基本的 Web 服务器
监听 GET 请求
//通过 app.get() 方法,可以监听客户端的 GET 请求,具体的语法格式如下:
监听 POST 请求
//通过 app.post() 方法,可以监听客户端的 POST 请求,具体的语法格式如下:
把内容响应给客户端
//通过 res.send() 方法,可以把处理好的内容,发送给客户端:
获取 URL 中携带的查询参数
//通过 req.query 对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数:
获取 URL 中的动态参数
//通过 req.params 对象,可以访问到 URL 中,通过 : 匹配到的动态参数:
托管静态资源
express.static()
express 提供了一个非常好用的函数,叫做 express.static(),通过它,我们可以非常方便地创建一个静态资源服务器
例如,通过如下代码就可以将 public 目录下的图片、CSS 文件、JavaScript 文件对外开放访问了
现在,你就可以访问 public 目录中的所有文件了:
http://localhost:3000/images/bg.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/login.js
因此,存放静态文件的目录名不会出现在 URL 中。
托管多个静态资源目录
如果要托管多个静态资源目录,请多次调用 express.static() 函数:
挂载路径前缀
如果希望在托管的静态资源访问路径之前,挂载路径前缀,则可以使用如下的方式
现在,你就可以通过带有 /public 前缀地址来访问 public 目录中的文件了:
http://localhost:3000/public/images/kitten.jpg
http://localhost:3000/public/css/style.css
http://localhost:3000/public/js/app.js
nodemon
它能够监听项目文件 的变动,当代码被修改后,nodemon 会自动帮我们重启项目,极大方便了开发和调试。
安装 nodemon
使用 nodemon
使用 nodemon app.js 来启动项目。这样做的好处是:代码 被修改之后,会被 nodemon 监听到,从而实现自动重启项目的效果。
Express路由
Express 中使用路由最简单的方式,就是把路由挂载到 app 上
模块化路由
创建路由模块
注册路由模块
为路由模块添加前缀
Express 中间件
中间件的概念
本质上就是一个 function 处理函数,中间件函数的形参列表中,必须包含 next 参数,next 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。而路由处理函数中只包含 req 和 res
Express 中间件的初体验
定义中间件函数
全局生效的中间件
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。
中间件的作用
多个中间件之间,共享同一份 req 和 res。基于这样的特性,我们可以在上游的中间件中,统一为 req 或 res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用。
定义多个全局中间件
按照中间件定义的先后顺序依次进行 调用
局部生效的中间件
定义多个局部中间件
中间件的分类
应用级别的中间件
通过 app.use() 或 app.get() 或 app.post() ,绑定到 app 实例上的中间件,叫做应用级别的中间件
路由级别的中间件
绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件
错误级别的中间件
错误级别中间件的作用,专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。
格式:错误级别中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是 (err, req, res, next)。
注意:错误级别的中间件, 必须注册在所有路由之后!
Express 内置的中间件
express.static【快速托管静态资源】 express.json【解析JSON格式的请求数据】
第三方的中间件
自定义中间件
使用 app.use() 来定义全局生效的中间件
监听 req 的 data 事件
在中间件中,需要监听 req 对象的 data 事件,来获取客户端发送到服务器的数据。如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以 data 事件可能会触 发多次,每一次触发 data 事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接。
监听 req 的 end 事件
当请求体数据接收完毕之后,会自动触发 req 的 end 事件。我们可以在 req 的 end 事件中,拿到并处理完整的请求体数据。
使用 querystring 模块解析请求体数据
Node.js 内置了一个 querystring 模块,专门用来处理查询字符串。通过这个模块提供的 parse() 函数,可以轻松把 查询字符串,解析成对象的格式。
将解析出来的数据对象挂载为 req.body
上游的中间件和下游的中间件及路由之间,共享同一份 req 和 res。因此,我们可以将解析出来的数据,挂载为 req 的自定义属性,命名为 req.body,供下游使用。
将自定义中间件封装为模块
为了优化代码的结构,我们可以把自定义的中间件函数,封装为独立的模块
Express 写接口
创建基本服务器
创建 API 路由模块
编写 GET 接口
编写 POST 接口
//如果要获取 URL-encoded 格式的请求体数据,必须配置中间件 app.use(express.urlencoded({ extended: false }))
CORS 跨域资源共享
接口的跨域问题
CORS(主流的解决方案,推荐使用)
JSONP(有缺陷的解决方案:只支持 GET 请求)
使用 cors 中间件解决跨域问题
cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件,可以很方便地解决跨域问题。 使用步骤分为如下 3 步:
运行 npm install cors 安装中间件
使用 const cors = require('cors') 导入中间件
在路由之前调用 app.use(cors()) 配置中间件
CORS概述:
CORS 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了 CORS 的接口。
CORS 在浏览器中有兼容性。只有支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 CORS 的服 务端接口
CORS 响应头部 - Access-Control-Allow-Origin
origin 参数的值指定了允许访问该资源的外域 URL。
如果指定了 Access-Control-Allow-Origin 字段的值为通配符 *,表示允许来自任何域的请求
CORS 响应头部 - Access-Control-Allow-Headers
默认情况下,CORS 仅支持客户端向服务器发送如下的 9 个请求头:Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、 Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)
如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过 Access-Control-Allow-Headers 对额外 的请求头进行声明,否则这次请求会失败!
CORS 响应头部 - Access-Control-Allow-Methods
默认情况下,CORS 仅支持客户端发起 GET、POST、HEAD 请求。如果客户端希望通过 PUT、DELETE 等方式请求服务器的资源,则需要在服务器端,通过 Access-Control-Alow-Methods 来指明实际请求所允许使用的 HTTP 方法。
CORS请求的分类
客户端在请求 CORS 接口时,根据请求方式和请求头的不同,可以将 CORS 的请求分为两大类
简单请求
预检请求
简单请求和预检请求的区别
简单请求的特点:客户端与服务器之间只会发生一次请求。 预检请求的特点:客户端与服务器之间会发生两次请求,OPTION 预检请求成功之后,才会发起真正的请求。
body-parser
Express中的中间件,用于处理HTTP请求体。它解析来自客户端发送的请求体数据,然后将其添加到 request 对象上,body-parser 提供了多种解析请求体的方式,包括:
json() :处理 JSON 格式的请求体。
urlencoded():处理 URL-encoded 格式的请求体。
text() :处理纯文本格式的请求体。
raw() :处理任何Buffer类型的请求体数据。
multipart() :解析 multipart/form-data 格式的请求体数据(常用于文件上传)。
下面是处理 JSON 格式请求体的示例代码:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// 解析 JSON 格式请求体
app.use(bodyParser.json());
app.post('/api/users', (req, res) => {
// 访问请求体中的数据
const user = req.body;
console.log(user);
res.send('User created successfully');
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
ps:body-parser 应该被添加在处理路由和其他请求之前,因为它必须能够解析请求体中的数据,以便在后续的路由处理中使用