在本教程中,您将构建一个用于添加、更新和删除待办事项的简单数据库,本教程将向您展示如何使用 Express 和 MySQL 创建 REST API。可以克隆此项目的 GitHub 存储库以进行跟进。让我们开始吧,好吗?

入门

本教程是一个动手演示。在开始之前,请确保您已准备好以下内容:

  • 已安装 MySQL 数据库
  • 安装了 Node.js

什么是 MySQL 数据库

MySQL 是一个开源的关系数据库管理系统 (RDBMS) (RDBMS)。它是最常使用 PHP 的数据库系统。MySQL 是一种云原生数据库解决方案,具有完整的管理功能。HeatWave 是内置的高速查询加速器,可将 MySQL 性能提高 5400 倍。

Oracle Corporation 创建、分发和维护 MySQL,它具有以下功能。

MySQL 数据库中的数据被组织成具有列和行的表。

  • MySQL 是一个基于服务器的数据库管理系统。
  • MySQL 是小型和大型项目的绝佳选择。
  • MySQL 是一个非常快速、可靠且易于使用的数据库系统。它使用普通的 SQL。
  • MySQL 在各种平台上运行。

项目设置

现在我们已经探索了 MySQL 数据库的全部内容,让我们开始创建我们的 RESTFul 应用程序。首先,我们需要使用以下命令为我们的项目创建一个文件夹:

mkdir rest-todos && cd rest-todos

上面的代码将创建一个 rest-todos 文件夹并将当前目录更改为它。然后,使用下面的命令,我们将创建一个新的 node.js 项目:

npm init -y

接下来,我们将安装我们项目所需的依赖项。

npm install express MySQL cors

创建我们的 Express 服务器

现在我们已经安装了依赖项,让我们创建一个app.js文件并在下面添加以下代码片段。我们将导入以下内容:

const express = require("express");
const cors = require("cors");
const AppError = require("./appError");
const errorHandler = require("./errorHandler");

接下来,我们从 express 创建一个应用实例,使用我们应用中的 express.json() 中间件来解析 URL 编码的正文。最后,我们让 API 路由器中间件监听到指定 URL 的传入请求。

然后,我们检查端点中缺少的 URL,如果它们被访问,则向用户抛出 404 错误。全局错误处理程序将处理我们将在后面的部分中设置它。

app.use(api, router);

app.all("*", (req, res, next) => {
 next(new AppError(`The URL ${req.originalUrl} does not exists`, 404));
});
app.use(errorHandler);

const PORT = 3000;
app.listen(PORT, () => {
 console.log(`server running on port ${PORT}`);
});

module.exports = app;

连接到 MySQL

现在让我们继续设置我们的 MySQL 数据库。首先,我们将使用以下命令打开我们的 MySQL shell:

mysql -u root -p

上面的命令将提示您输入 root 密码。输入密码并按 Enter 键继续。

然后,通过运行下面的 SQL 语句从您的 MySQL shell 创建一个数据库。

创建数据库

然后,通过运行以下 SQL 语句创建任务列表表。该表将具有 id、name、status、date_created 字段。id 是我们表的主键。

CREATE TABLE tasklist(id int NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL, 
status varchar(50), 
date_created DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
PRIMARY KEY (id));

接下来,创建一个dbConfig.js文件并将下面的代码片段添加到它以将应用程序连接到 MySQL 数据库。

const mysql = require('mysql');
const connection = mysql.createConnection({
 host: "localhost",
 user: "root",
 password: "1234",
 database: "todo",
});

connection.connect();

module.exports = connection;

创建我们的控制器

让我们开始构建我们的应用程序的路由。

在我们的项目根目录中创建一个控制器文件夹,然后在控制器文件夹中创建一个app.js文件。

我们的全局错误处理程序和 MySQL 数据库连接将首先被导入。

const AppError = require("./appError");
const conn = require("./dbConfig");

下一步是设置我们的getAll处理程序,它将检索我们数据库中的所有待办事项。此处理程序将使用 MySQL 查询方法,该处理程序将 SQL 查询和回调函数作为输入。如果操作期间发生错误,我们将使用AppError该类向用户返回错误。

exports.getAll = (req, res, next) => {
 conn.query("SELECT * FROM tasklist", function (err, data, fields) {
   if(err) return next(new AppError(err))
   res.status(200).json({
     status: "success",
     length: data?.length,
     data: data,
   });
 });
};

接下来,创建我们的createTask处理程序以将新的待办事项添加到我们的数据库中。首先,我们需要在保存数据之前检查用户是否发送了一个空表单。

exports.createTask = (req, res, next) => {
 if (!req.body) return next(new AppError("No form data found", 404));
 const values = [req.body.name, "pending"];
 conn.query(
   "INSERT INTO tasklist (name, status) VALUES(?)",
   [values],
   function (err, data, fields) {
     if (err) return next(new AppError(err, 500));
     res.status(201).json({
       status: "success",
       message: "todo created!",
     });
   }
 );
};

然后,为了通过 ID 获取待办事项,我们开发了一个 getTask 处理程序。首先,我们将查看请求字段中是否提供了 id,如果没有,我们将向客户端返回错误。

exports.getTask = (req, res, next) => {
 if (!req.params.id) {
   return next(new AppError("No todo id found", 404));
 }
 conn.query(
   "SELECT * FROM tasklist WHERE id = ?",
   [req.params.id],
   function (err, data, fields) {
     if (err) return next(new AppError(err, 500));
     res.status(200).json({
       status: "success",
       length: data?.length,
       data: data,
     });
   }
 );
};

接下来,为了更新我们的待办事项,我们将编写我们的 updateTask 处理程序,它将编辑待完成的 id 在请求参数中的待办事项。

exports.updateTask = (req, res, next) => {
 if (!req.params.id) {
   return next(new AppError("No todo id found", 404));
 }
 conn.query(
   "UPDATE tasklist SET status='completed' WHERE id=?",
   [req.params.id],
   function (err, data, fields) {
     if (err) return next(new AppError(err, 500));
     res.status(201).json({
       status: "success",
       message: "todo updated!",
     });
   }
 );
};

最后,为了从我们的数据库中删除一个待办事项,我们将创建一个 deleteTask 处理程序。要删除 id 为请求参数的待办事项,我们将使用 delete 语句。

exports.deleteTask = (req, res, next) => {
 if (!req.params.id) {
   return next(new AppError("No todo id found", 404));
 }
 conn.query(
   "DELETE FROM tasklist WHERE id=?",
   [req.params.id],
   function (err, fields) {
     if (err) return next(new AppError(err, 500));
     res.status(201).json({
       status: "success",
       message: "todo deleted!",
     });
   }
 );
}

创建我们的错误处理程序

现在我们已经设置了所有的 API 控制器,让我们继续使用下面的代码片段创建我们的错误类函数:

class AppError extends Error {
 constructor(msg, statusCode) {
   super(msg);

   this.statusCode = statusCode;
   this.error = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
   this.isOperational = true;

   Error.captureStackTrace(this, this.constructor);
 }
}
module.exports = AppError;

然后,在不停止我们的程序的情况下,检查可能的问题并将相关的错误和状态代码传递给客户端。

module.exports = (err, req, res, next) => {
 err.statusCode = err.statusCode || 500;
 err.status = err.status || "error";
 res.status(err.statusCode).json({
   status: err.status,
   message: err.message,
 });
};

创建路线

现在让我们创建 API 路由来访问我们的控制器。创建一个 router.js 文件并添加以下代码片段:

const express = require("express");
const controllers = require("./controllers");
const router = express.Router();

router.route("/").get(controllers.getAllTodos).post(controllers.createTodo);
router
 .route("/:id")
 .get(controllers.getTodo)
 .put(controllers.updateTodo)
 .delete(controllers.deleteTodo);
module.exports = router;

现在更新 app.js 文件以使用以下代码片段导入我们的路由器:

...
const router = require("./router")
app.use("task/", router);
...

结论

在本教程中,您学习了如何通过创建 todo 应用程序在 Node.js 中构建 REST API。您向刚刚构建的应用程序添加更多功能,例如身份验证和授权。