后端实战教程:如何使用 Node.js 开发 RESTful API 接口(Node.js + Express + Sequelize + MySQL)

A kitten
蒋川
B 端数据开发,卡拉云联合创始人
最近更新 2022年06月27日

如何使用 Node.js 开发 RESTful API 接口(Node.js + Express + Sequelize + MySQL) 本教程手把手教你搭建一套使用 Node.js + Express + Sequelize + MySQL 构建的后端服务,详细描述通过 Node.js 与数据库通讯。整个服务搭建起来后,我们使用 Postman 对整个后端服务进行测试。本教程每段代码我都亲手测过,保证百分百没有错误,请打开你的 terminal 跟随本教程一起操作,从这里开始,成为一名后端工程师。

全栈实战教程:

后端实战教程:

如果你正在搭建后台管理工具,又不想处理前端问题,推荐使用卡拉云,卡拉云是新一代低代码开发工具,可一键接入常见数据库及 API ,无需懂前端,仅需拖拽即可快速搭建属于你自己的后台管理工具,一周工作量缩减至一天,详见本文文末。

crud-er

后端部分:node.js + Express + Sequelize + MySQL

  • node.js 是整个后端的框架
  • 使用 Express 生成
  • Sequelize ORM
  • MySQL

后端部分 - node.js + Express + MySQL 后端部分

后端部分我们使用 node.js + Express + MySQL 的方式来构建。node.js 是一个开源跨平台运行环境,它让 JavaScript 可以运行在后端服务器上,Express 是 node.js Web app 框架,其底层是对 node.js 的 HTTP 模块封装,增加路由,中间件等特性,我们会在本教程中使用 Express 搭建 RESTful API ,让前后端通过 API 进行数据交换。最后是 MySQL 数据库,最终前后端操作的数据会存放在 MySQL 数据库中。

后端 node.js 项目结构

06-01-node

  • db.config.js 包含远程连接 MySQL 数据库的登录参数
  • server.js 包含 Express Web 服务器初始化配置
  • models/index.js 包含 MySQL 数据库的配置信息
  • models/todo.model.js : 包含 Sequelize 数据模型
  • controllers/todo.controller.js:包含所有增删改查操作的路由

好了,整体的后端服务器架构介绍就到这里,接下来进入实践环节,请打开你的 Terminal 我们一起来。切记,只有亲手实践过,才能透彻理解。

安装 node.js

node.js 是一种 JavaScript 的运行环境,它可以让 JS 脱离浏览器在后端服务器上运行。本教程的后端环境使用 node.js 搭建。请先确认你的计算机中是否已安装 node.js 。如果尚未安装请前往 node 官网下载安装

安装或准备可远程连接的 MySQL 数据库

本教程搭建的 app 数据存放在 MySQL 中,你可以在本机安装 MySQL ,也可以准备一台可远程连接的 MySQL 数据库。

如果你还没有安装 MySQL 数据库,可根据《如何安装 MySQL》教程安装 MySQL 数据库,或在腾讯云之类的云服务商购买现成的 MySQL 数据库。

准备好 node.js 和 MySQL 数据库后,咱们就开始搭建后端部分。

创建 node.js App

在根目录创建 node.js 的项目文件夹

mkdir nodejs-express-sequelize-mysql-kalacloud
cd nodejs-express-sequelize-mysql-kalacloud

接下来配置后端的所有操作都在 nodejs-express-sequelize-mysql-kalacloud 这个文件夹中完成。

我们先来初始化 node.js,使用 npm init 配置 package.json 文件。package.json 定义了当前项目所需要的各种模块以及项目配置信息(包含当前项目所需的开发和运行环境等信息)。

npm init

06-02-node-init

npm init
name: (nodejs-express-sequelize-mysql)
version: (1.0.0)
description: Node.js Rest Apis with Express, Sequelize , MySQL.
entry point: (index.js) server.js
test command:
git repository:
keywords: nodejs, express, sequelize, mysql, rest, api
author: kalacloud
license: (ISC)
Is this ok? (yes) yes

跟随 node.js 初始化程序填写相应的 app 初始化信息。

{
  "name": "nodejs-mysql-kalacloud-com",
  "version": "1.0.0",
  "description": "Node.js Rest Apis with Express, Sequelize , MySQL.",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "nodejs",
    "express",
    "sequelize",
    "mysql",
    "rest",
    "api"
  ],
  "author": "kalacloud",
  "license": "ISC"
}

初始化程序填写完成之后,npm 会自动帮你在根目录下生成package.json 配置文件。

接着我们来安装项目中需要用到的模块:expresssequelizemysql2body-parser

在项目根目录 nodejs-express-sequelize-mysql-kalacloud 执行 npm 命令:

npm install express sequelize mysql2 body-parser cors --save

配置 Express Web 服务器

在根目录中,创建一个新的 server.js 文件

文件位置:nodejs-express-sequelize-mysql-kalacloud/server.js

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");

const app = express();

var corsOptions = {
  origin: "*"
};

app.use(cors(corsOptions));

// content-type:application/json
app.use(bodyParser.json());

// content-type:application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));

// 简单路由
app.get("/", (req, res) => {
  res.json({ message: "欢迎访问卡拉云后端服务器" });
});

// 设置监听端口
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`服务器运行端口: ${PORT}.`);
});
  • 我们导入了 expressbody-parsercors 模块
  • express 用于构建 Rest API 帮助前后端实现通讯。
  • body-parser 用于解析请求并创建 req.body 对象
  • cors 提供 Express 中间件
  • corsOptions 这里设置了可访问后端的前端来源为 * ,这意味着任何前端都可以接入此后端。这样设置并不安全,为了避免「跨域问题」,先这么设置。之后请在这里限制可访问的前端服务器。
  • 后端服务在 8080 端口上侦听指令

06-03-node-server

好,现在我们在根目录运行指令:node server.js 启动后端服务器。

node-chrome

在浏览器中输入 http://localhost:8080 ,你可以看到后端服务器欢迎信息,这表明我们的后端服务器已经启动。

使用 Sequelize 连接数据库

Sequelize 是一个基于 Promise 的 Node.js ORM,目前支持 Postgres、MySQL、SQLite 和 Microsoft SQL Server。 它是一个很成熟的框架,有很好的性能和速度。

我们先来配置 Sequelize ,在根目录新建 app 文件夹,然后再其中建一个 config 文件夹,我们把 Sequelize 的配置文件放在这里,新建 db.config.js 文件,在这个文件中写入你数据库连接的配置信息。

文件位置:nodejs-express-sequelize-mysql-kalacloud/app/config/db.config.js

module.exports = {
  HOST: "192.168.1.5",
  USER: "kalacloud",
  PASSWORD: "YOUR_PASSWORD",
  DB: "demo",
  port:3306,
  dialect: "mysql",
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
};
  • HOST 这里是你的 MySQL 服务器地址,如果数据库跑在本地就是 loaclhost,如果在腾讯云等云服务上,就填写云服务给你的数据库地址,比如 cdb-5nvdsixo.bj.tencentcdb.com 这是腾讯云的数据库地址样式。
  • USER 数据库登录用户名
  • PASSWORD 用户名对应的登录密码
  • DB 数据库名称
  • port 数据库远程访问端口
  • max 最大连接数
  • min 最小连接数
  • acquire 超时时间
  • idle 空闲时间

更多细节可访问 Sequelize 参数映射表 查看更多

初始化 Sequelize

我们将在 app / models 文件夹中初始化 Sequelize。

app/models 新建 index.js 文件并写入以下代码。

文件位置:nodejs-express-sequelize-mysql-kalacloud/app/models/index.js

const dbConfig = require("../config/db.config.js");

const Sequelize = require("sequelize");
const sequelize = new Sequelize(dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD, {
  host: dbConfig.HOST,
  dialect: dbConfig.dialect,
  operatorsAliases: false,

  pool: {
    max: dbConfig.pool.max,
    min: dbConfig.pool.min,
    acquire: dbConfig.pool.acquire,
    idle: dbConfig.pool.idle
  }
});

const db = {};

db.Sequelize = Sequelize;
db.sequelize = sequelize;

db.todos = require("./todo.model.js")(sequelize, Sequelize);

module.exports = db;

这里的todo.model.js 是一个用来操作数据库的 sequelize 模型,用于前端发出指令,后端接受指令后操作数据库,后文会具体讲解。本文的前端配套教程《全栈实战:手把手教你用 Vue+Nodejs 开发「待办清单」app

然后在根目录下的 server.js 文件里添加 sync() 调用的方法:

文件位置:nodejs-express-sequelize-mysql-kalacloud/server.js

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");

const app = express();

var corsOptions = {
  origin: "http://localhost:8081"
};

app.use(cors(corsOptions));

// content-type:application/json
app.use(bodyParser.json());

// content-type:application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));

// 简单路由
app.get("/", (req, res) => {
  res.json({ message: "欢迎访问卡拉云后端服务器" });
});

// 设置监听端口
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`服务器运行端口: ${PORT}.`);
});

const db = require("./app/models");
db.sequelize.sync();

在结尾处添加这两行即可,你可以直接把 server.js 里的代码全删掉,然后复制上面的代码进去,保证你的项目代码与本教程完全一致。

定义 Sequelize Model

models 文件夹中,像这样创建 todo.model.js 文件

文件位置:nodejs-express-sequelize-mysql-kalacloud/app/models/todo.model.js

module.exports = (sequelize, Sequelize) => {
  const Todo = sequelize.define("todo", {
    title: {
      type: Sequelize.STRING
    },
    description: {
      type: Sequelize.STRING
    },
    status: {
      type: Sequelize.BOOLEAN
    }
  });

  return Todo;
};

Sequelize Model 是向 MySQL 中指定数据库的写入列,这里会自动生成 ID,title,description,status,createdAt,updatedAt 这六个列。

初始化 Sequelize 之后,我们不需要在写任何增删改查函数,直接调就可以了。

  • 创建一个新清单:[create](https://sequelize.org/master/class/lib/model.js~Model.html#static-method-create)(object)
  • 通过 id 查找清单:[findByPk](https://sequelize.org/master/class/lib/model.js~Model.html#static-method-findByPk)(id)
  • 获取所有待办清单:[findAll](https://sequelize.org/master/class/lib/model.js~Model.html#static-method-findAll)()
  • 根据 ID 更新清单:[update](https://sequelize.org/master/class/lib/model.js~Model.html#static-method-update)(data, where: { id: id })
  • 根据 ID 删除清单:[destroy](https://sequelize.org/master/class/lib/model.js~Model.html#static-method-destroy)(where: { id: id })
  • 删除所有清单:destroy(where: {})
  • 在所有清单中按标题查找:findAll({ where: { title: ... } })

是不是超级方便,这些函数,我们会在接下来创建的「控制器」中使用。

创建控制器(controllers)

app/controllers 文件夹中,我们来创建一个控制器 todo.controller.js ,把上面 Sequelize 写入控制器来操作数据。

文件位置:nodejs-express-sequelize-mysql-kalacloud/app/controllers/todo.controller.js

const db = require("../models");
const Todo = db.todos;
const Op = db.Sequelize.Op;

// 创建并保存一条清单
exports.create = (req, res) => {
  // Validate request
  if (!req.body.title) {
    res.status(400).send({
      message: "内容不能为空"
    });
    return;
  }

  // 创建一条清单
  const todo = {
    title: req.body.title,
    description: req.body.description,
    stauts: req.body.stauts ? req.body.stauts : false
  };

  // 将清单保存到数据库
  Todo.create(todo)
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "创建清单是发生错误。"
      });
    });
};

// 从数据库中搜索.
exports.findAll = (req, res) => {
  const title = req.query.title;
  var condition = title ? { title: { [Op.like]: `%${title}%` } } : null;

  Todo.findAll({ where: condition })
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "搜索时,发生错误。"
      });
    });
};

// 按照条目 ID 搜索
exports.findOne = (req, res) => {
  const id = req.params.id;

  Todo.findByPk(id)
    .then(data => {
      if (data) {
        res.send(data);
      } else {
        res.status(404).send({
          message: `没有找到 ${id} 的清单`
        });
      }
    })
    .catch(err => {
      res.status(500).send({
        message:  `查询第 ${id} 条清单时出错`
      });
    });
};

// 更新指定 ID 清单
exports.update = (req, res) => {
  const id = req.params.id;

  Todo.update(req.body, {
    where: { id: id }
  })
    .then(num => {
      if (num == 1) {
        res.send({
          message: "更新成功"
        });
      } else {
        res.send({
          message: `${id} 条更新失败。`
        });
      }
    })
    .catch(err => {
      res.status(500).send({
        message: `更新第 ${id} 条清单时出错`
      });
    });
};

// Delete a Todo with the specified id in the request
exports.delete = (req, res) => {
  const id = req.params.id;

  Todo.destroy({
    where: { id: id }
  })
    .then(num => {
      if (num == 1) {
        res.send({
          message: "删除成功"
        });
      } else {
        res.send({
          message: `删除第${id}条清单失败。`
        });
      }
    })
    .catch(err => {
      res.status(500).send({
        message: "不能删除清单:" + id
      });
    });
};

// 删除数据库中所有清单
exports.deleteAll = (req, res) => {
  Todo.destroy({
    where: {},
    truncate: false
  })
    .then(nums => {
      res.send({ message: `删除${nums}条清单 ` });
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "删除所有清单时出错"
      });
    });
};

// 检查所有清单状态
exports.findAllstauts = (req, res) => {
  Todo.findAll({ where: { stauts: true } })
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "搜索清单时出错"
      });
    });
};

至此,整个后端部分就搭建完成了,我们把后端运行起来看看效果。

运行 Node.js Express 服务器

在 node.js 服务器根目录,运行 node server.js

06-04-node-all-server

控制台显示对数据库的读写,每当前端调用后端时,这里就会给出对应后端操作了写什么的 log

使用 Postman 调用 node.js 后端测试 API

06-06-postman

后端搭建起来后,我们可以使用 postman 来对它进行测试。

扩展阅读:

Vue + Node.js 前后端分离搭建实战,手把手教你用 Vue+Nodejs 开发「待办清单」app

Node.js 后端搭建总结

Node.js 接收前端指令,根据前端指令操作数据库 CRUD,相当方便。学会前后端是成为全栈工程师的基础技能。但如果你只想专注在解决实际问题,不想写代码,推荐使用卡拉云,卡拉云内置多种常用组件,无需懂前后端,仅需拖拽即可快速生成你需要的后台管理工具。

下面是用卡拉云搭建的数据库 CURD 后台管理系统,只需拖拽组件,即可在10分钟内完成搭建。

卡拉云 SQL admin 后台管理系统

可直接分享给同事一起使用:https://my.kalacloud.com/apps/8z9z3yf9fy/published

卡拉云是新一代低代码开发平台,与市面上主流前端框架相比,卡拉云无需配置开发环境,直接注册即可开始搭建。开发者无需处理任何前端问题,简单拖拽即可生成表格、表单、富文本等功能组件,一键接入数据库及 API,快速完成企业内部工具搭建,还可以分享给团队成员共享使用,数周的开发时间,缩短至 1 小时。