摘要: 在本教程中,您将了解 Express 路由,这是一个定义端点 (URI) 并在客户端请求这些端点时响应的过程。
Express 路由简介
端点是特定 URL (统一资源定位符) 或路径以及 HTTP 方法 (GET、POST、PUT、…)
通常,端点代表客户端可以执行的特定资源或功能,例如获取数据、修改数据和删除记录。
例如,以下端点检索待办事项列表
GET /todos
在此端点中,路径为 /todos
,HTTP 方法为 GET
。
以下端点创建一个新的待办事项
POST /todos
路径也是 /todos
,但 HTTP 为 POST
。
在 Express 中,路由是关于设置端点并定义当客户端请求这些端点时应用程序应该如何响应。
路由定义了您的应用程序如何处理对端点的请求。要定义路由,您使用 Express
对象的方法(例如 get、post、put、patch 和 delete)以及
以下是定义路由的语法
app.method(path, handler);
Code language: JavaScript (javascript)
在此语法中
app
是Express
应用程序的实例。method
是小写形式的 HTTP 请求方法,例如get
、post
、put
、patch
和delete
。path
是服务器上的路径。handler
是在匹配路由时执行的函数。路由处理程序可以访问req
和res
对象,它们分别对应于 HTTP 请求和响应对象。
基本路由示例
以下定义了对根 URL (‘/’) 的 GET
请求的路由
app.get('/', (req, res) => {
res.send('Hello World');
});
Code language: PHP (php)
类似地,以下定义了对 '/about'
的 GET
请求的路由
app.get('/about', (req, res) => {
res.send('About Page');
});
Code language: PHP (php)
以下示例定义了对 '/login'
的 POST
请求的路由
app.post('/login', (req, res) => {
res.send('Authenticated');
});
Code language: PHP (php)
Express 路由示例
让我们创建一个包含几个路由的 Express 应用程序。
创建 Express 应用程序
步骤 1. 打开您的终端或命令提示符,并创建一个新目录,例如 express-routing
mkdir express-routing
cd express-routing
Code language: JavaScript (javascript)
步骤 2. 运行以下 npm
命令来初始化项目
npm init -y
Code language: JavaScript (javascript)
这将创建一个 package.json
文件,其中包含配置、脚本和依赖项。
步骤 3. 通过从终端运行以下 npm
命令来安装 Express
npm install express
Code language: JavaScript (javascript)
步骤 4. 将 .env
文件添加到项目中,并将 PORT
设置为 3000
PORT=3000
Code language: JavaScript (javascript)
步骤 5. 将以下键值对添加到 package.json
文件中,以指示 Node.js 使用 ES 模块
"type": "module"
Code language: JavaScript (javascript)
此外,将 scripts
部分更改为以下内容
"scripts": {
"start": "node --watch index.js"
},
Code language: JavaScript (javascript)
这允许您运行 npm start
命令以使用 --watch
标志执行 index.js
文件。
步骤 6. 使用以下代码创建一个 index.js
文件
import express from 'express';
const app = express();
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
Code language: JavaScript (javascript)
步骤 7. 通过从终端运行以下命令来启动服务器
npm start
Code language: JavaScript (javascript)
步骤 8. 创建一个 api.http
文件,用于使用 VS Code 中的 REST Client 扩展程序向路由发出请求。
添加路由
步骤 1. 创建一个新的模块 todos.js
模块,它导出待办事项数组和返回下一个待办事项 ID 的函数
export const todos = [
{ id: 1, title: 'Learn Node.js', completed: true },
{ id: 2, title: 'Master Express', completed: false },
{ id: 3, title: 'Build an API Server', completed: false },
];
export const nextTodoId = () => {
// get the next id for the todo
let maxId = 1;
todos.forEach((todo) => {
if (todo.id > maxId) {
maxId = todo.id;
}
});
return maxId + 1;
};
Code language: JavaScript (javascript)
步骤 2. 将 todos
数组和 nextTodoId
函数从 todo.js
模块导入到 index.js
模块中
import { todos, nextTodoId } from './todos.js';
Code language: JavaScript (javascript)
步骤 3. 为对 '/api/todos/'
端点的 GET 请求定义路由
import express from 'express';
import { todos, nextTodoId} from './todos.js';
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/api/todos/', (req, res) => {
res.send(todos);
});
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
Code language: JavaScript (javascript)
步骤 4. 通过将 HTTP 请求添加到 /api/todos
端点来修改 api.http
# Get all todos items
GET http://localhost:3000/api/todos/
Code language: JavaScript (javascript)
当对 /api/todos/
端点发出 GET 请求时,将执行路由处理程序,它将以 JSON 数据的形式响应 todos
数组
[
{
"id": 1,
"title": "Learn Node.js",
"completed": true
},
{
"id": 2,
"title": "Master Express",
"completed": false
},
{
"id": 3,
"title": "Build an API Server",
"completed": false
}
]
Code language: JavaScript (javascript)
将查询字符串添加到路由
要检索已完成或未完成的待办事项列表,您可以将查询字符串附加到路由 /api/todos
,如下所示
http://localhost:3000/api/todos/?completed=true
Code language: JavaScript (javascript)
或
http://localhost:3000/api/todos/?completed=false
Code language: JavaScript (javascript)
URL 中问号 (?
) 之后的所有内容都称为查询字符串。在我们的示例中,查询字符串如下所示
completed=false
Code language: JavaScript (javascript)
查询字符串可能包含一个或多个参数,其中每个参数都由一个唯一的键值对表示,这些键值对由等号 (=
) 分隔。
要从 Express 中的 URL 访问查询字符串,请使用 req.query
对象,如下所示
req.query
Code language: JavaScript (javascript)
例如
// ...
app.get('/api/todos/', (req, res) => {
console.log(req.query);
});
// ...
Code language: JavaScript (javascript)
如果您对端点 http://localhost:3000/api/todos/?completed=false
发出 GET 请求,您将在控制台中看到以下查询对象
{ completed: 'false' }
Code language: JavaScript (javascript)
要访问查询字符串中的 completed
参数,可以使用以下内容
app.get('/api/todos/', (req, res) => {
console.log(req.query.completed);
});
Code language: JavaScript (javascript)
以下修改了 /api/todos/
端点,以在 completed
查询字符串可用时返回未完成/已完成的待办事项
app.get('/api/todos/', (req, res) => {
if (req?.query?.completed) {
const isCompleted = req.query.completed === 'true';
const filteredTodos = todos.filter(
(todo) => todo.completed === isCompleted
);
res.send(filteredTodos);
}
res.send(todos);
});
Code language: JavaScript (javascript)
以下是更新后的 api.http
文件版本
# Get all todos items
GET http://localhost:3000/api/todos/
###
# Get incompleted todo items:
GET http://localhost:3000/api/todos/?completed=false
###
# Get completed todo items:
GET http://localhost:3000/api/todos/?completed=true
Code language: JavaScript (javascript)
处理路由参数
路由段是命名 URL 段,用于捕获在 URL 中其位置指定的值。例如
http://localhost:3000/api/todos/1
Code language: JavaScript (javascript)
在此 URL 中,1 是表示待办事项 ID 的路由参数。
在 Express 中,您可以使用 id 设置路由,如下所示
/api/todo/:id
Code language: JavaScript (javascript)
要访问路由参数,请使用 req.params
对象
req.params
Code language: JavaScript (javascript)
在路由 /api/todo/:id
中,id
是 req.params
对象的键。因此,您可以使用以下内容访问它
req.params.id
Code language: JavaScript (javascript)
请注意,路由参数的值始终是字符串。因此,您需要将它们转换为所需类型的值。
以下定义了返回具有 ID 的待办事项的路由
app.get('/api/todos/:id', (req, res) => {
const { id } = req.params;
const todoId = parseInt(id);
if (isNaN(todoId)) {
res.status(400).send(`Invalid id ${id}`);
}
const todo = todos.find((todo) => todo.id === todoId);
if (todo) res.status(200).send(todo);
res.status(404).send(`Todo with id ${id} not found`);
});
Code language: JavaScript (javascript)
它是如何工作的。
首先,通过解构对象从 req.params
对象中获取 id
const { id } = req.params;
Code language: JavaScript (javascript)
其次,将 id 值转换为整数。如果 id 不是数字,则以 HTTP 状态码 400 响应,并附带错误消息
const todoId = parseInt(id);
if (isNaN(todoId)) {
res.status(400).send(`Invalid id ${id}`);
}
Code language: JavaScript (javascript)
第三,查找具有该 id 的待办事项,并将其作为 JSON 返回给客户端
const todo = todos.find((todo) => todo.id === id);
if (todo) res.send(todo);
Code language: JavaScript (javascript)
最后,如果找不到具有该 id 的待办事项,则返回 HTTP 状态码 404
res.status(404).send(`Todo with id ${id} not found`);
Code language: JavaScript (javascript)
将它们整合在一起
以下显示了已完成的 index.js
模块
import express from 'express';
import { todos, nextTodoId } from './todos.js';
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/api/todos/', (req, res) => {
if (req?.query?.completed) {
const isCompleted = req.query.completed === 'true';
const filteredTodos = todos.filter(
(todo) => todo.completed === isCompleted
);
res.send(filteredTodos);
}
res.send(todos);
});
app.get('/api/todos/:id', (req, res) => {
const { id } = req.params;
const todoId = parseInt(id);
if (isNaN(todoId)) {
res.status(400).send(`Invalid id ${id}`);
}
const todo = todos.find((todo) => todo.id === todoId);
if (todo) res.status(200).send(todo);
res.status(404).send(`Todo with id ${id} not found`);
});
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
Code language: JavaScript (javascript)
总结
- 端点是指客户端可以使用来访问资源或执行操作功能的特定 URL(或路径)和 HTTP 方法。
- 路由定义了应用程序如何响应特定端点。
- 使用 Express 应用程序对象的方法来定义路由。