Build a REST API with Node.js, Express, and MySQL
Build a REST API with Node.js, Express, and MySQL
在本教程中,我们将学习如何使用 MySQL 作为我们的数据库和 Node.js 作为我们的语言来构建 REST API。
我们还将使用 Express.js 框架来简化我们的任务。我们的示例 REST API 将跟踪最流行的编程语言。
先决条件
- 了解 MySQL 和关系数据库的一般工作方式
- Node.js和Express的基本知识.js
- 了解什么是 REST(具象状态传输)API 以及它们如何工作
- 了解什么是 CRUD(创建、读取、更新、删除)以及它与 HTTP 方法的关系、、 和
GET``POST``PUT``DELETE
什么是MySQL?
MySQL是世界上最受欢迎的数据库之一,如果不是最流行的。根据 2020 年堆栈溢出调查,MySQL 是最受欢迎的数据库,超过 55% 的受访者使用它。社区版是免费提供的,由一个庞大而活跃的社区提供支持。
docker 安装mysql
docker中下载 mysql
docker pull mysql
启动
docker run -p 3306:3306 --name mysql -v /opt/docker_v/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=765365 -d [imageID]
命令说明:
-p 3306:3306:将容器的3306端口映射到主机的3306端口 -v /opt/docker_v/mysql/conf:/etc/mysql/conf.d:将主机/opt/docker_v/mysql/conf目录挂载到容器的/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456:初始化root用户的密码 -d: 后台运行容器,并返回容器ID imageID: mysql镜像ID
进入容器
docker exec -it mysql bash
登录mysql
mysql -u root -p
ALTER USER 'root'@'localhost' IDENTIFIED BY '786345!';
添加远程登录用户
CREATE USER 'xq'@'%' IDENTIFIED WITH mysql_native_password BY '786345!';
GRANT ALL PRIVILEGES ON *.* TO 'xq'@'%';
CRUD集成
初始化项目
mkdir programming-languages-api && cd programming-languages-api
要使用 Express.js 服务器设置 Node.js 应用程序,我们首先要为我们的项目创建一个目录:
然后,我们可以使用 npm init -y 创建一个 package.json 文件,如下所示:
npm init -y
{
"name": "programming-languages-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
要安装 Express,我们将运行 npm i express,将 Express 添加为 package.json 文件中的依赖项。接下来,我们将在 index.js 文件中创建一个 slim 服务器。 它将在主路径 / 上打印一条 ok 消息:
const express = require("express");
const app = express();
const port = 3000;
//使用内置的 Express JSON 解析器中间件来解析 JSON
app.use(express.json());
app.use(
// express.urlencoded() 中间件来解析 URL 编码主体
express.urlencoded({
extended: true,
})
);
app.get("/", (req, res) => {
res.json({ message: "ok" });
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
REST API 项目结构
我们将按以下方式构建我们的项目,以在文件夹中逻辑安排我们的文件:
config.js
将包含信息的配置,例如数据库凭据和我们希望在对结果进行分页时每页显示的行。
helper.js
是任何辅助函数的家,比如计算分页的偏移量。
routes/programmingLanguages.js
文件将充当 URI 和 services/programmingLanguages.js 服务中相应函数之间的粘合剂。 服务文件夹将存放我们所有的服务。 其中之一是 db.js,我们用它来与 MySQL 数据库对话。
另一个服务是 programmingLanguages.js,它将具有 getMultiple、create 等方法来获取和创建编程语言资源。 URI 和相关服务功能的基本映射类似于以下代码:
GET /programming-languages → getMultiple()
POST /programming-languages → create()
PUT /programming-languages/:id → update()
DELETE /programming-languages/:id → remove()
现在,让我们编写带有分页的 GET 编程语言 API。
配置数据库连接
要创建我们的 GET 编程语言 API,我们需要将我们的 Node.js 服务器与 MySQL 链接起来。 为此,我们将使用 npm 中的 mysql2 包,我们可以在项目根目录下使用 npm i mysql2
命令安装它。
安装依赖
npm i mysql2
项目的根目录下创建配置文件
config.js
const config = {
db: {
/* don't expose password or any sensitive info, done only for demo */
host: "101.43.18.117",
user: "xq",
password: "xq123!",
database: "test",
},
listPerPage: 10,
};
module.exports = config;
分页配置
helper.js
function getOffset(currentPage = 1, listPerPage) {
return (currentPage - 1) * [listPerPage];
}
function emptyOrRows(rows) {
if (!rows) {
return [];
}
return rows;
}
module.exports = {
getOffset,
emptyOrRows
}
持久层编写
services/db.js
我们将连接到数据库并在 services/db.js 文件中启用对数据库的运行查询语句
// 导入mysql模块
const mysql = require('mysql2/promise');
// 获取数据库配置
const config = require('../config');
// 自定义查询语句函数
async function query(sql, params) {
const connection = await mysql.createConnection(config.db);
const [results, ] = await connection.execute(sql, params);
return results;
}
module.exports = {
query
}
服务层编写
services/programmingLanguage.js
const db = require('./db');
const helper = require('../helper');
const config = require('../config');
async function getMultiple(page = 1){
const offset = helper.getOffset(page, config.listPerPage);
const rows = await db.query(
`SELECT id, name, released_year, githut_rank, pypl_rank, tiobe_rank
FROM programming_languages LIMIT ${offset},${config.listPerPage}`
);
const data = helper.emptyOrRows(rows);
const meta = {page};
return {
data,
meta
}
}
module.exports = {
getMultiple
}
路由层编写
处理url业务
const express = require('express');
const router = express.Router();
// 路由层调用服务层,服务层调用持久层,持久层调用数据库连接层
const programmingLanguages = require('../services/programmingLanguage');
/* GET programming languages. */
router.get('/', async function(req, res, next) {
try {
res.json(await programmingLanguages.getMultiple(req.query.page));
} catch (err) {
console.error(`Error while getting programming languages `, err.message);
next(err);
}
});
module.exports = router;
程序入口注入路由
index.js
const express = require("express");
const app = express();
const port = 3000;
// 导入路由
const programmingLanguagesRouter = require("./routes/programmingLanguages");
// json格式
app.use(express.json());
app.use(
express.urlencoded({
extended: true,
})
);
app.get("/", (req, res) => {
res.json({ message: "ok" });
});
// 注入路由
app.use("/programming-languages", programmingLanguagesRouter);
/* Error handler middleware */
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
console.error(err.message, err.stack);
res.status(statusCode).json({ message: err.message });
return;
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
查询效果

第三方API集成
在本节中,我们将构建一个调用 Node.js 中的 API 的小程序。稍后,我将介绍一个示例应用程序,希望它可以展示 API 调用如何适合更大的 Web 应用程序。
1.在 RapidAPI 上注册一个免费帐户
2.订阅API
https://rapidapi.com/developer/dashboard
查找星座信息并不能发挥 API 的全部功能。然而,RapidAPI 有一个有趣的娱乐类别,可以很好地用于小型应用程序。
3.设置项目
打开一个新的终端。
在终端中运行以下命令。
$ mkdir node-api-call
$ cd node-api-call
$ npm init -y
这些命令创建一个新目录,将终端移动到该目录中,并初始化一个新的 Node.js 项目。
现在我们已经初始化了一个 Node.js 项目,我们可以安装模块了。
4.安装模块
npm install --save axios
5.获取调用js
const axios = require("axios");
const encodedParams = new URLSearchParams();
encodedParams.append("q", "English is hard, but detectably so");
const options = {
method: 'POST',
url: 'https://google-translate1.p.rapidapi.com/language/translate/v2/detect',
headers: {
'content-type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'application/gzip',
'X-RapidAPI-Key': 'yourapikey',
'X-RapidAPI-Host': 'google-translate1.p.rapidapi.com'
},
data: encodedParams
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
6.进行异步API调用
translateConfig.js
底层调用实现
const axios = require("axios");
const BASE_URL = `https://google-translate1.p.rapidapi.com`
const encodedParams = (q, target, source) => {
const encodedParams = new URLSearchParams();
encodedParams.append("q", q);
encodedParams.append("target", "zh");
encodedParams.append("source", "en");
return encodedParams;
};
module.exports = {
translateMessage: (content, source, target) => axios({
method: "POST",
url: BASE_URL + `/language/translate/v2`,
headers: {
'content-type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'application/gzip',
'X-RapidAPI-Key': 'yourapikey',
'X-RapidAPI-Host': 'google-translate1.p.rapidapi.com'
},
data: encodedParams(content, target, source),
})
}
translateApi.js
进行接口封装
const AstrologyAPI = require('./translateConfig')
const translateApi = async (translate) => {
console.log(translate.contents)
const response = await AstrologyAPI.translateMessage(translate.contents, 'en', 'zh')
return response.data.data.translations[0];
}
module.exports = {
translateApi
}
7.路由层新增
const thirdApi = require('../services/translateApi')
/* translate */
router.post('/translate', async function (req, res, next) {
try {
console.log(req.body)
res.json(await thirdApi.translateApi(req.body));
} catch (err) {
console.error(`Error while translate `, err.message);
next(err);
}
});
8.效果

代码地址
node-back/Express-Mysql-Crud at main · dabaoqiang/node-back (github.com)