# Express

https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/Express_Nodejs

# 1. Express 框架简介

# 1.1 Express 框架是什么

Express 是一个基于 Node 平台的 web 应用开发框架,它提供了一系列的强大特性,帮助你创建各种 Web 应用。我们可以使用 npm install express 命令进行下载。

# 1.2 Express 框架特性

提供了方便简洁的路由定义方式 对获取 HTTP 请求参数进行了简化处理 对模板引擎支持程度高,方便渲染动态 HTML 页面 提供了中间件机制有效控制 HTTP 请求 拥有大量第三方中间件对功能进行扩展

# 1.3 Express 框架路由

// 当客户端以get方式访问/时
app.get("/", (req, res) => {
  // 对客户端做出响应
  res.send("Hello Express");
});
// 当客户端以post方式访问/add路由时
app.post("/add", (req, res) => {
  res.send("使用post方式请求了/add路由");
});

# 1.4 Express 框架获取请求参数

app.get("/", (req, res) => {
  // 获取GET参数
  console.log(req.query);
});

app.post("/", (req, res) => {
  // 获取POST参数
  console.log(req.body);
});

# 1.5 Express 初体验

使用 Express 框架创建 web 服务器及其简单,调用 express 模块返回的函数即可。

// 引入Express框架
const express = require("express");
// 使用框架创建web服务器
const app = express();
// 当客户端以get方式访问/路由时
app.get("/", (req, res) => {
  // 对客户端做出响应 send方法会根据内容的类型自动设置请求头
  res.send("Hello Express"); // <h2>Hello Express</h2> {say: 'hello'}
});
// 程序监听3000端口
app.listen(3000);

# 2. 中间件

# 2.1 什么是中间件

中间件就是一堆方法,可以接收客户端发来的请求、可以对请求做出响应,也可以将请求继续交给下一个中间件继续处理。

中间件主要由两部分构成,中间件方法以及请求处理函数。 中间件方法由 Express 提供,负责拦截请求,请求处理函数由开发人员提供,负责处理请求。

app.get("请求路径", "处理函数"); // 接收并处理get请求
app.post("请求路径", "处理函数"); // 接收并处理post请求

可以针对同一个请求设置多个中间件,对同一个请求进行多次处理。 默认情况下,请求从上到下依次匹配中间件,一旦匹配成功,终止匹配。 可以调用 next 方法将请求的控制权交给下一个中间件,直到遇到结束请求的中间件。

app.get("/request", (req, res, next) => {
  req.name = "张三";
  next();
});
app.get("/request", (req, res) => {
  res.send(req.name);
});

# 2.2 中间件用法

app.use 匹配所有的请求方式,可以直接传入请求处理函数,代表接收所有的请求。

app.use((req, res, next) => {
  console.log(req.url);
  next();
});

app.use 第一个参数也可以传入请求地址,代表不论什么请求方式,只要是这个请求地址就接收这个请求。

app.use("/admin", (req, res, next) => {
  console.log(req.url);
  next();
});

# 2.3 中间件应用

路由保护,客户端在访问需要登录的页面时,可以先使用中间件判断用户登录状态,用户如果未登录,则拦截请求,直接响应,禁止用户进入需要登录的页面。 网站维护公告,在所有路由的最上面定义接收所有请求的中间件,直接为客户端做出响应,网站正在维护中。 自定义 404 页面

# 2.4 错误处理中间件

在程序执行的过程中,不可避免的会出现一些无法预料的错误,比如文件读取失败,数据库连接失败。

错误处理中间件是一个集中处理错误的地方。

app.use((err, req, res, next) => {
  res.status(500).send("服务器发生未知错误");
});

当程序出现错误时,调用 next()方法,并且将错误信息通过参数的形式传递给 next()方法,即可触发错误处理中间件。

app.get("/", (req, res, next) => {
  fs.readFile("/file-does-not-exist", (err, data) => {
    if (err) {
      next(err);
    }
  });
});

# 2.5 捕获错误

在 node.js 中,异步 API 的错误信息都是通过回调函数获取的,支持 Promise 对象的异步 API 发生错误可以通过 catch 方法捕获。 异步函数执行如果发生错误要如何捕获错误呢?

try catch 可以捕获异步函数以及其他同步代码在执行过程中发生的错误,但是不能其他类型的 API 发生的错误。

app.get("/", async (req, res, next) => {
  try {
    await User.find({
      name: "张三"
    });
  } catch (ex) {
    next(ex);
  }
});

# 3. Express 请求处理

# 3.1 构建模块化路由

// home.js
const home = express.Router();
home.get("/index", () => {
  res.send("欢迎来到博客展示页面");
});
module.exports = home;
// admin.js
const home = express.Router();
home.get("/index", () => {
  res.send("欢迎来到博客列表页面");
});
module.exports = list;
// app.js
const home = require("./route/home.js");
const admin = require("./route/admin.js");
app.use("/home", home);
app.use("/admin", admin);

# 3.2 GET 参数的获取

Express 框架中使用 req.query 即可获取 GET 参数,框架内部会将 GET 参数转换为对象并返回。

// 接收地址栏中问号后面的参数
// 例如: http://localhost:3000/?name=zhangsan&age=30
app.get("/", (req, res) => {
  console.log(req.query); // {"name": "zhangsan", "age": "30"}
});

# 3.3 POST 参数的获取

Express 中接收 post 请求参数需要借助第三方包 body-parser。

// 引入body-parser模块
const bodyParser = require("body-parser");
// 配置body-parser模块
app.use(
  bodyParser.urlencoded({
    extended: false
  })
);
// 接收请求
app.post("/add", (req, res) => {
  // 接收请求参数
  console.log(req.body);
});

# 3.4 Express 路由参数

app.get("/find/:id", (req, res) => {
  console.log(req.params); // {id: 123}
});

# 3.5 静态资源的处理

通过 Express 内置的 express.static 可以方便地托管静态文件,例如 img、CSS、JavaScript 文件等。

app.use(express.static("public"));