1 什么是Express
Express 是一个基于 Node.js 的 Web 应用程序框架。它提供了一组简洁而强大的工具和功能,用于开发 Web 和 API 服务器端应用程序。
Express提供了一系列中间件(middlewares)和路由(routing)功能,以处理请求、响应和中间处理逻辑,同时提供了模板引擎支持、静态文件服务、错误处理等功能。
Express 的优势在于其简洁性和灵活性,可以根据需要选择和集成其他中间件、插件和功能来满足具体的开发需求。它被广泛用于构建 Web 应用程序、API 服务器、单页应用程序等,是 Node.js 生态系统中最受欢迎和常用的框架之一。
2 安装express
在 Node.js 中可以通过使用 Node 包管理器(npm)来安装express:
- 打开terminal,切换到项目目录
npm init
初始化项目npm i express
安装express模块,这会从 npm 仓库下载 Express 包及其依赖,并将其安装到你的项目的node_modules
目录下- 在你的代码文件中引入express模块
const express = require('express')
3 express搭建简单web服务器
安装好express框架后,我们可以利用它搭建一个简单的web服务器:
const express = require('express');
const app = express(); //app:express应用程序对象
const port = 3000;
// 处理根路由
app.get('/', (req, res) => {
res.send('Hello, Express!');
});
// 启动服务器
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
在第2行中,我们调用express()
函数,并将返回值赋给变量app
。借助变量app
,我们启动服务器、监听端口 3000,并处理根路由 /
的 GET 请求。当客户端发起 GET 请求到根路径时,服务器将发送响应 "Hello, Express!"。
note:express()
函数返回一个对象,该对象具有许多可用于创建服务器的方法和属性,我们将其称为Express 应用程序对象并赋值给变量app
。
通过使用Express应用程序对象(即
app
),你可以定义路由、处理请求和响应、设置应用程序的配置等等。它是构建 Express 服务器的核心对象。
Express 应用程序对象具有一些重要的方法和属性,例如:
app.listen()
:用于启动服务器并监听指定的端口。app.get()
、app.post()
、app.put()
、app.delete()
等:路由处理函数,根据请求的路径和HTTP方法执行相应操作。app.use()
:用于添加中间件函数来处理请求。app.set()
、app.get()
:用于设置和获取应用程序的设置。app.locals
:用于存储应用程序的本地变量。app.router
:用于路由处理的中间件。
4 express处理不同http请求方法
4.1 GET
const fs = require('fs');
const express = require('express');
const app = express();
const tours = JSON.parse(
fs.readFileSync(`${__dirname}/dev-data/data/tours-simple.json`, 'utf-8')
);
app.get('/api/v1/tours', (req, res) => {
res.status(200).json({
status: 'success',
results: tours.length,
data: {
tours,
},
});
});
const port = 3000;
app.listen(port, () => {
console.log(`App running on port ${port}...`);
});
在上面的代码中,9~17行是处理GET请求的代码,其中我们做了一些事:
- 使用
app.get()
函数定义get方法的路由和路由处理函数(route & route handler)。 res.status()
函数是 Express 中用于设置响应的 HTTP 状态码的方法。它允许你在发送响应之前设置响应的状态码。res.json()
方法是 Express 中用于发送 JSON 响应的方法。它将一个 JavaScript 对象或数组转换为 JSON 字符串,并将其作为响应的主体发送给客户端。res.json()
方法会自动设置响应的 Content-Type 为application/json
。
4.2 POST
...
app.use(express.json()); //middleware
...
app.post('/api/v1/tours', (req, res) => {
const newId = tours[tours.length - 1].id + 1;
const newTour = Object.assign({ id: newId }, req.body);
tours.push(newTour);
fs.writeFile(
`${__dirname}/dev-data/data/tours-simple.json`,
JSON.stringify(tours),
(err) => {
res.status(201).json({
status: 'success',
data: {
tour: newTour,
},
});
}
);
});
在上面的代码中,我们做了一些事:
- 使用中间件函数
app.use(express.json())
,用于解析传入请求的JSON数据。当客户端发送带有 JSON 数据的 POST 请求(或 PUT 请求)时,通常需要将请求体中的 JSON 数据解析为 JavaScript 对象,以便在服务器端进行处理。express.json()
中间件就是用来完成这个解析过程的。 - 我们希望将tours写入tours-simple.json文件,但tours是js对象, 因此在12行,使用
JSON.stringfy()
函数将js对象转换为json字符串,以写入json文件。
4.3 获取路由参数
路由参数是在URL路径中的一部分,用于标识和区分不同的资源或页面,使用冒号(:)来定义,并在URL中使用对应的值来替代。
示例:/users/:id
,其中:id
是路由参数,可以匹配任何具体的用户ID值。
express提供了req.params
对象用以获取用户请求中的路由参数。
app.get('/api/v1/tours/:id', (req, res) => {
const id = req.params.id * 1;
const tour = tours.find((el) => el.id === id);
if (!tour) {
return res.status(404).json({
status: 'fail',
message: 'Invalid ID',
});
}
res.status(200).json({
status: 'success',
data: {
tour,
},
});
});
在上面的代码中:
req.params
是 Express 中用于获取路由参数的对象。如果客户端发送的请求路径是/api/v1/tours/5
,那么req.params
的值将为{id:'5'}
。- 第2行中,将文本值转换为数值
4.4 PATCH
PATCH
和 PUT
是 HTTP 协议中用于更新资源的方法,区别在于:
PUT
方法用于替换整个资源,要求提供完整的资源表示。可以创建或完全替换资源。PATCH
方法用于局部更新资源,只需提供要更新的字段或属性。保持其他字段不变。
app.patch('/api/v1/tours/:id', (req, res) => {
if (req.params.id * 1 > tours.length) {
return res.status(404).json({
status: 'fail',
message: 'Invalid ID',
});
}
res.status(200).json({
status: 'success',
data: {
tour: '<Updated our tour...>',
},
});
});
4.5 DELETE
app.delete('/api/v1/tours/:id', (req, res) => {
if (req.params.id * 1 > tours.length) {
return res.status(404).json({
status: 'fail',
message: 'Invalid ID',
});
}
res.status(204).json({
status: 'success',
data: null
});
});
note:状态码 204 表示 "No Content",它表示服务器成功处理了请求,但没有返回任何内容作为响应。
4.6 路由重构
我们可以将上面所有操作的路由和路由处理函数分开。
const getAllTours = (req, res) => {...};
const getTour = (req, res) => {...};
const createTour = (req, res) => {...};
const updateTour = (req, res) => {...};
const deleteTour = (req, res) => {...};
app
.route('/api/v1/tours') //路由对象
.get(getAllTours)
.post(createTour);
app
.route('/api/v1/tours/:id')
.get(getTour)
.patch(updateTour)
.delete(deleteTour);
在上面的代码中,我们做了两件数:
- 将路由处理函数定义到处理程序外部。
- 使用
app.route()
创建链式路由处理程序。 它可以用于在一个地方定义针对同一路径的多个 HTTP 方法的处理逻辑,提高代码的可读性和可维护性。