文章目录
express 模块
express 简介
express 是基于
Node.js
的 http 创建出的平台,开放、极简的 web 开发框架。本质上是
npm 的第三方包。中文官网:
http://www.expressjs.com.cn/
作用:
- 专门提供 web 网页资源的服务器(web 网站服务器)
- 专门对外提供 api 接口的服务器(API 接口服务器)
express 的基本使用
安装:
npm i express@4.17.1
创建基本的 web 服务器
//导入
const express = require("express");
//创建服务器
const app = express();
//调用app.listen
app.listen(8080, () => {
console.log("server running at http://127.0.0.1:8080");
});
监听 GET和POST 请求
通过
app.get()
方法,可以监听客户端的 get 请求。
语法格式:
app.get("请求URL", function (req, res) {
/*处理函数*/
});
参数解读:
'请求URL'
: 客户端请求的 url 地址function (req, res) { /*处理函数*/ }
: 请求的处理函数- req : 请求对象(包含了与请求相关的属性与方法)
- res:响应对象(包含了与响应有关的属性和方法)
通过
app.post()
方法,可以监听客户端的 get 请求。
语法格式:
app.post("请求URL", function (req, res) {
/*处理函数*/
});
参数解读:
-
'请求URL'
: 客户端请求的 url 地址 -
function (req, res) { /*处理函数*/ }
: 请求的处理函数- req : 请求对象(包含了与请求相关的属性与方法)
- res:响应对象(包含了与响应有关的属性和方法)
把内容响应给客户端
使用
res.send()
方法。
app.get("/user", (req, res) => {
//向客户端发送JSON对象
res.send({ name: "tom", age: 30, gender: "男" });
});
app.post("/user", (req, res) => {
console.log("请求成功!");
});
获取 url 中携带的查询参数
通过
res.query()
对象,可以访问到客户端查询字符串的形式,发送到服务器的参数
app.get("/", (req, res) => {
//req.query 默认是空对象
//客户端发送 ?name=zs&age=20
// 可以通过req.query查询到
// req.query.name req.query.age
console.log(req.query);
});
练习:
const express = require("express");
const app = express();
app.get("/user", (req, res) => {
console.log(req.query);
res.send({ name: "tom", age: 40, gender: "男" });
});
app.post("/user", (req, res) => {
console.log("请求成功");
});
app.listen(8080, () => {
console.log("server running at http://127.0.0.1:8080");
});
结果:
通过
req.params
对象,可以访问到 url 中通过:
匹配到的动态参数(例如:http://127.0.0.1/user/:id
)
app.get("/user/:id", (req, res) => {
console.log(req.params);
});
结果:
托管静态资源
express.static()
通过这个函数,可以很方便地创建一个静态资源服务器。例如,通过如下代码将 public 目录下的图片、css 文件、js 文件对外开放访问。
app.use(express.static("public"));
注意:
express 在静态目录查找文件,并对外提供资源的访问路径。但是存放静态资源的目录名不会出现在URL中
- http://localhost:3000/images/bg.png
- http://localhost:3000/css/style.css
- http://localhost:3000/js/login.js
挂载路径前缀
app.use("public", express.static("public"));
访问路径变成如下:
- http://localhost:3000/public/images/bg.png
- http://localhost:3000/public/css/style.css
- http://localhost:3000/public/js/login.js
nodemon
当代码修改时,
nodemon
可以帮我们重启项目,方便开发和调试。
安装 nodemon
//安装nodemon全局工具
npm i nodemon -g
使用 nodemon
nodemon app.js
express 路由
初识路由
路由指的是
客户端的请求
与服务器处理函数
之间的映射关系
express 的路由由请求的类型
、请求的URL地址
、处理函数
格式:
app.METHOD(PATH, HANDLER);
例子:
//匹配GET请求 且URL为 /
app.get("/", function (req, res) {
res.send("hello world");
});
//匹配POST请求 且URL 为 /
app.post("/", function (req, res) {
res.send("Get a post request");
});
module.exports = router;
路由的匹配过程
当有一个请求到达服务器之后,需要先进行路由的匹配,只有匹配成功之后,才会调用对应的处理函数。
模块化路由
为了方便对路由进行模块化的管理,express 不建议将路由直接挂载到 app 上,而是推荐将路由抽离为单独的模块。
步骤:
- 创建路由模块对应的.js 文件
- 调用
express.Router()
函数创建路由对象 - 向路由对象上挂载具体的路由
- 使用
module.exports
向外共享路由对象 - 使用
app.use()
注册路由模块
var express = require("express"); // 导入express
var router = express.Router(); // 创建路由对象
router.get("/user/list", (req, res) => {
res.send("Get user list");
});
router.post("/user/add", (req, res) => {
res.send("add new user");
});
注册路由
app.use(router);
为路由添加前缀
和为静态资源统一挂载访问前缀一样
const userRouter = require("./router/user.js");
//使用app.use()注册模块 并添加前缀
app.use("api", userRouter);
中间件
当一个请求到达 express 服务器时,可以调用多个中间件,从而对这次请求进行
预处理
。
格式:
本质上是 function 函数
注意:
中间件函数的形参列表中,必须包含next参数
。而路由处理函数只包含 req,res.
next 函数的作用
next 函数是实现多个中间件连续调用的关键,它表示把流转关系移交给了下一个中间件或路由。
定义中间件函数
const mw = function (req, res, next) {
console.log("这是一个中间件函数");
//当处理完此中间件的业务时,必须调用next()函数
next();
};
全局生效的中间件
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。通过调用
app.use(中间件函数)
,计科定义一个全局生效中间件
代码:
const mw = function (req, res, next) {
console.log("这是一个中间件函数");
next();
};
//全局生效
app.use(mw);
简化形式:
app.use(function (req, res, next) {
console.log("");
next();
});
中间件的作用
多个中间件之间,
共享同一份req和res
,基于这样的特性,我们可以在上游的中间件中,同意为 req 和 res 添加自定义的属性或方法,供下游的中间件使用。
定义多个全局中间件
可以使用
app.use()
连续定义多个全局中间件,服务器会安装定义的前后顺序依次调用
app.use(function (req, res, next) {
console.log("1");
next();
});
app.use(function (req, res, next) {
console.log("2");
next();
});
app.use(function (req, res, next) {
console.log("3");
next();
});
app.use(function (req, res, next) {
console.log("4");
next();
});
局部生效的中间件
不使用
app.use()
定义的中间件,叫做局部生效的中间件
,代码:
// 定义中间件
const mw1 = function (req, res, next) {
console.log("中间件函数");
next();
};
//mw1中间件只在当前路由中生效’
app.get("/", mw1, function (req, res) {
res.send("Home page");
});
//mw1中间件不会影响这个路由↓↓
app.get("/user", function (req, res) {
console.log("user page");
});
定义多个局部中间件
可以在路由中,通过如下两种等价的方式:
app.get("/", mw1, mw2, function (req, res) {
res.send("Home page");
});
app.get("/", [mw1.mw2], function (req, res) {
res.send("Home page");
});
注意事项:
- 一定要在路由之前注册中间件
- 客户端发来的请求,可以连续调用多个中间件进行处理
- 执行完中间件的业务代码之后,要调用
next()
函数 - 在调用
next()
之后不要再写额外的代码 - 连续调用多个中间件时,多个中间件之间,共享 req 和 res
错误级别的中间件
专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题
格式:
function(err,req,res,next){}
注意
:
必须注册在所有路由之后
express 内置中间件
express.static()
快速托管静态资源(无兼容性)express.json()
解析 JSON 格式的请求体数据 (4.16.0+)express.urlencoded()
解析 url-encoded 格式的请求体数据(4.16.0+)
//配置解析json格式
app.use(express.json());
//配置urlencoded
app.use(express.urlencoded({ extended: false }));
第三方中间件
非官方内置,按需下载
例如:body-parser中间件
解析请求体
- 安装
body-parser
中间件 - 使用
require()
导入中间件 - 调用
app.use()
注册并使用中间件
自定义中间件
步骤:
- 定义中间件
- 监听 req 的 data 事件
- 监听 req 的 end 事件
- 使用
querystring
模块解析请求体数据 - 将解析出来的数据对象挂载为 req.body
- 将自定义中间件封装为模块
编写 GET 和 POST 请求
apiRouter.js
const express = require("express");
const router = express.Router();
router.get("/get", (req, res) => {
// 获取请求字符串
const query = req.query;
res.send({
status: 0, // 状态 0:成功; 1: 失败
msg: "Get请求成功!", //状态描述
data: query, // 响应给客户端的数据
});
});
router.post("/post", (req, res) => {
const body = req.body;
console.log(body);
res.send({
status: 0,
msg: "Post请求成功",
data: body,
});
});
module.exports = router;
GET 和 POST 请求
const express = require("express");
const app = express();
const port = 8080;
//解析表单数据 一定要在请求之前
app.use(express.urlencoded({ extended: false }));
const router = require("./apiRouter");
app.use("/api", router);
app.listen(port, () => {
console.log(`server running port at ${port}`);
});
解决跨域问题
当客户端和服务端协议不同时,使用 ajax 并不能发送成功。
使用 cors 中间件解决跨域问题
cors 由一系列 http 响应头组成,决定了浏览器是否阻止前端 js 代码跨域获取资源
浏览器的安全同源策略
默认会阻止网页“跨域”获取资源,当配置 cors 响应头之后就可以解除限制。(有兼容性问题)
- 安装
npm i cors
- 导入
require('cors')
- 在路由器之前调用 app.use(cors())
const cors = require("cors");
app.use(cors());
cors 相关的响应头
- Access-control-Allow-Origin
// 例:允许所有
res.setHeader("Access-control-Allow-Origin", "*");
- Access-control-Allow-Headers
- 默认情况下,cors 仅支持客户端向服务器发送九个请求头,如果发送了额外的请求头信息,则需要在服务器端,通过
Access-control-Allow-Headers
声明,否则请求就会失败
- Access-control-Allow-Methods
- 默认情况下,cors 仅支持客户端发送 get、post、head 请求
,如果希望视同 put、delete 请求资源,则需要在服务器端,通过Access-control-Allow-Methods
来致命实际请求所允许使用的 http 方法