使用 Node.js 开发 RESTful API 接口(Node.js + Express + Sequelize + MySQL)

1,852 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

概述

今天我们使用 Node.js + Express + Sequelize + MySQL, 构建一个后端服务,来详细的介绍下 通过 Nodejs 与数据库的通讯。

创建项目

后端部分我们使用 Nodejs + Express + MySQL,的方式来构建。开始前需要准备 nodejs 环境,MySQL 数据库环境。

首先我们新建一个文件夹

mdkir  nodejs-express-sequelize-mysql
cd nodejs-express-sequelize-mysql

然后在文件根目录初始化项目

npm init --yes

控制台输出如下内容

Wrote to /Users/handeqin/space/nodejs-express-sequelize-mysql/package.json:

{
  "name": "nodejs-express-sequelize-mysql",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

初始化完成后,我们来添加项目中需要的模块

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

配置 Express Web 服务器

在根目录, 创建一个新的 app.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-parsecors 模块
  • `express 主要用于构建 Rest API 帮助前后端实现通讯
  • body-parse 用于解析请求并创建 req.body 对象
  • cors 提供 Express 中间件
  • corsOptions 这里设置了可访问后端来源为 *,意味着任何前端都可以和当前后端进行通讯,这样设置是不安全的,不过暂时为了避免跨域问题,先这样设置,之后再做处理
  • 后端服务在 8080 端口上监听

我们值终端执行 node app.js

可以看到输出了

服务器运行端口: 8080.

接着在浏览器输入 localhost:8080,就可以看到欢迎信息了,这说明我们的项目已经正常启动了

使用 Sequelize 连接数据库

Sequelize 是一个基于 PromiseNodejs ORM, 目前支持 PostgresMySQLSQLiteMicrosoft SQL Server。 它是一个很成熟的框架,有很好的性能和速度。

我们先来配置 Sequelize, 在根目录新建 app 文件夹,然后在建一个 config 文件夹,

src/app/config/db.config.js

module.exports = {
  HOST: "192.168.1.5",
  USER: "zhijianqiu",
  PASSWORD: "123456",
  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

新建一个文件 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 模型,用于前端发出指令,后端接受指令后操作数据库,后文会具体讲解。

接着在根目录下的 app.js 文件最后添加 sync() 调用的方法

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

定义 Sequelize Model

在 models 文件夹中,创建 todoModel.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(object)
  • 通过 id 查找清单:findByPk(id)
  • 获取所有待办清单:findAll()
  • 根据 ID 更新清单:(data, where: { id: id })
  • 根据 ID 删除清单:destroy(where: { id: id })
  • 删除所有清单:destroy(where: {})
  • 在所有清单中按标题查找:findAll({ where: { title: ... } })

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

创建控制器(controllers)

在 app/controllers/todoController.js 文件中,把上面 Sequelize 写入控制器来操作数据

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 app.js, ok 项目运行正常