跟我一起练--用Node写个可以操作MySQL的接口

前言

以前也用Node写过接口,但不涉及数据库操作。而我们发现,自己公司的后端写接口,基本都绕不开数据库操作。感觉不写一个能操作数据库的接口,就不算真正意义上学会了写接口。那我们今天就学习一下,如何写一个可以操作数据库的接口。下面我们进入正题。

创建Express项目

Express 是一个简洁而灵活的Node Web应用框架, 通过对底层接口进行封装,在简化代码的同时提供更强大的接口,大幅度提升开发效率和体验,将开发者从冗长、复杂、易错的代码中解放出来。与创建Vue和React应用一样,创建Express项目也有脚手架可供使用。express-generator是Express的应用生成器,用它可以快速创建一个Express的应用骨架。

生成项目

安装express-generator并生成一个名为nodeApi的Express Web应用,命令如下:

bash 复制代码
npm i -g express-generator
express nodeApi

生成的项目目录结构如下:

express项目目录简介:

bin:可执行文件。里面包含了一个启动文件 www 默认监听端口是 3000。

public:静态文件。用来存放项目静态文件如js+css以及图片。

routes:路由文件。路由主要定义url和 资源的映射关系, 用来接收前端发送的请求,把响应数据给前端

views:后端视图模版文件。

app.js:入口文件。

运行项目

推荐使用pnpm安装项目依赖,速度比npm要快一些。安装完依赖之后启动项目,后端服务不像前端项目,会自动打开一个页面。

bash 复制代码
pnpm install && node bin/www

需在浏览器地址栏输入http://localhost:3000/, 如果能看到如下界面,说明项目启动正常。

使用Docker安装MySQL

为什么不直接安装MySQL,而要使用Docker安装MySQL呢?因为Docker能保证运行环境的一致性,不会出现开发环境,测试环境,生产环境同样的配置表现不一致的问题。其次,我看公司的生产环境也是在Docker上运行MySQL。

安装Docker

笔者使用的是Win操作系统,Windows下Docker的安装方法参见此文。如果Win系统提示无法安装Docker,那你需要开启一下Hyper-V功能,如果Hyper-V 虚拟机监控程序处于禁用状态,那你需要在开机的时候进入BIOS中,修改一下虚拟技术配置(不同品牌的电脑设置有差异,请自行搜索一下)。

运行MySQL

docker安装完成之后,需要重启电脑。重启之后运行docker,然后在命令行执行拉取MySQL镜像命令

docker pull mysql:latest

在docker中安装完MySQL后,使用以下命令来运行mysql容器:

bash 复制代码
docker run -itd --name mysql-test -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql

参数说明:

  • -itd 以交互模式在后台运行容器
  • --name设置容器名称
  • -p 3306:3306 :映射容器服务的 3306 端口到宿主机的 3306 端口,外部主机可以直接通过 宿主机ip:3306 访问到 docker容器的MySQL的服务。
  • -e MYSQL_ROOT_PASSWORD=123456 :设置 MySQL服务 root 用户的密码。

运行结果如图所示:

另外再补充两条命令,因为docker的bash中没有vi/vim指令, 造成修改mysql配置文件困难。为了解决这个问题,可以先把docker中的mysql配置文件复制到主机,修改完成之后,再用主机修改之后的配置文件覆盖docker中的mysql配置文件。

复制docker容器文件到主机

bash 复制代码
docker cp 容器id:/etc/my.cnf ./my.cnf

将主机文件复制到docker容器

bash 复制代码
docker cp ./my.cnf 容器id:/etc/my.cnf

创建数据

在MySQL中创建数据有两种方式,第一种是使用SQL命令,第二种是使用可视化工具(推荐第二种)。

用SQL命令

bash 复制代码
# step1 查看容器id
docker ps
# step2 进入docker命令行模式
docker exec -it 容器id ./bin/bash
# step3 输入密码登录mysql
mysql -u root -p
# step4 创建数据库并插入数据
create database demo character set utf8mb4 collate utf8mb4_unicode_ci;
use demo;
# 创建表
create table users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  mobile VARCHAR(100) NOT NULL
);
# 向表中插入数据
insert into users (name, mobile) values  ('zhangsan', '13800000000');
insert into users (name, mobile) values ('lisi', '13800000001');
# 查看数据
select * from users;
# 退出mysql
quit;
# 退出docker容器命令行(非SQL命令)
exit

用可视化工具

windows上推荐安装Navicat数据库管理工具软件,下载安装之后,创建连接, 界面配置参数如下:

连接成功之后, 进入到demo数据库的users表,可以看到之前用SQL命令插入的数据。添加删除一条数据点击一下底部的+,-号即可,比用SQL命令方便一些。

编写接口操作数据库功能

借助Knex操作数据库

为什么要用Knex操作MySQL,而不是直接使用npm中的mysql/mysq2工具包? 因为npm的mysql/mysq2在复杂查询、迁移和事务处理上,需要手动操作数据库,而且也不支持Promise链式调用。

Knex.js 是一个功能齐全的 SQL 查询构造器(query builder),支持 PostgreSQL、CockroachDB、MSSQL、MySQL、MariaDB、SQLite3、Better-SQLite3、Oracle 和 Amazon Redshift 等数据库,同时支持传统 node 风格的 callback 回调和更加简洁的 promise异步接口,还支持 stream 接口、 全功能的 query(查询 和 schema(模式)构造器、事务(支持保存点)、pooling(连接池),并且对不同的查询客户端以及 SQL 方言的执行结果进行了标准化。

安装knex和mysql2

注意要安装的mysql依赖包名叫mysql2而不是mysql, 前面我们安装的是最新版MySQL,最新版的MySQL服务端不支持低版本mysql客户端的加密方式,连接时会报错。需要改成高版本的MySQL客户端 依赖包mysql2,才能正常连接。

bash 复制代码
pnpm add knex mysql2

创建数据库配置文件

数据库配置文件config.js内容如下,实际使用时这段代码不能提交到代码仓库,要把敏感信息都写入到环境变量里,这里仅作演示.

js 复制代码
const configs = {
  mysql: {
    host: "localhost",
    port: "3306",
    user: "root", // 数据库用户
    password: "123456", // 数据库密码
    database: "demo", // 数据库的名字
  },
  // 打印错误
  log: {
    error(message) {
      console.log("[knex error]", message);
    },
  },
};

module.exports = configs;

编写基本功能

js 复制代码
const configs = require("../config");
const knex = require("knex")({
  // 链接配置
  connection: {
    host: configs.mysql.host,
    port: configs.mysql.port,
    user: configs.mysql.user,
    password: configs.mysql.password,
    database: configs.mysql.database,
  },
  // 客户端版本
  client: "mysql2",
  // 打印错误
  log: {
    error(message) {
      console.log("[knex error]", message);
    },
  },
});

class Base {
  constructor(props) {
    this.table = props.table;
  }

  // 新增
  insert(params) {
    return knex(this.table).insert(params);
  }

  // 更改
  update(id, params) {
    return knex(this.table).where("id", "=", id).update(params);
  }

  // 删除
  delete(id) {
    return knex(this.table).where("id", "=", id).del();
  }

  // 查找
  query() {
    return knex(this.table).select();
  }
}

module.exports = Base;

编写主程序

接下来我们按照MVC的业务逻辑组织模式,实现主程序功能。先写增改删查的控制器功能。代码功能一看就懂,这里就不详细解释了。

js 复制代码
// 引用用户模版数据
const User = require("../models/user.js");

const userController = {
  // 获取用户数据
  queryUser: async (req, res, next) => {
    try {
      let resData = await User.query();
      res.json({
        code: 200,
        message: "操作成功",
        data: resData,
      });
    } catch (e) {
      res.json({ code: 0, message: "操作失败", data: e });
    }
  },
  // 添加用户数据
  addUser: async (req, res, next) => {
    try {
      let resData = await User.insert(req.body);
      res.json({
        code: 200,
        message: "操作成功",
        data: resData,
      });
    } catch (e) {
      res.json({ code: 0, message: "操作失败", data: e });
    }
  },
  // 更新用户数据
  updateUser: async (req, res, next) => {
    const { id, params } = req.body;
    try {
      let resData = await User.update(id, params);
      res.json({
        code: 200,
        message: "操作成功",
        data: resData,
      });
    } catch (e) {
      res.json({ code: 0, message: "操作失败", data: e });
    }
  },
  // 删除用户数据
  delUser: async (req, res, next) => {
    try {
      let resData = await User.delete(req.body.id);
      res.json({
        code: 200,
        message: "操作成功",
        data: resData,
      });
    } catch (e) {
      res.json({ code: 0, message: "操作失败", data: e });
    }
  },
};

module.exports = userController;

接着写控制器引用的模型文件功能,主要是继承数据库基础操作Base类的功能,支持配置表格名称。

js 复制代码
const Base = require("./base");

class User extends Base {
  // 定义参数默认值为 user 表
  constructor(props = { table: "users" }) {
    super(props);
  }
}
module.exports = new User();

再看看路由文件,定义请求URL和相应方法的对应关系。

js 复制代码
const express = require("express");
const router = express.Router();
const userController = require("../controllers/user");

// ...

// 获取用户信息
router.get("/get_user", userController.queryUser);
// 新增用户信息
router.post("/add_user", userController.addUser);
// 修改用户信息
router.post("/update_user", userController.updateUser);
// 删除用户信息
router.post("/del_user", userController.delUser);

module.exports = router;

最后在入口文件app.js中,引入路由配置

js 复制代码
const express = require("express");
var usersRouter = require("./routes/users");
const usersRouter = require("./routes/users");

const app = express();
// 支持json参数
app.use(express.json());
app.use("/users", usersRouter);

为了修改代码能热更新,需要全局安装一下nodemon

bash 复制代码
npm i -g nodemon

并修改一下package.json中的服务启动命令,然后重启服务。

js 复制代码
  "scripts": {
    "start": "nodemon ./bin/www"
  },

重启之后,用postwoman请求express服务接口,验证一下接口响应是否正确。可以看到,响应正常。

在Navicat查看,这条数据已经插入到demo数据库中的users表了。至此我们已经实现了通过接口操作数据库功能。

结尾

通过本文的介绍,我们了解了如何使用 Express 框架写接口操作 MySQL 数据库。从Express应用的创建、到MySQL数据库的安装,连接配置和数据库的基本操作命令,以及接口Api的编码和测试方法,我们一步步构建了一个完整的可以操作MySQL数据库的Express应用程序。掌握这些了技能,你已经向全栈开发迈进了一步,如果想在全栈的道路上走得更远,还需要学习消息队列,微服务架构,性能优化,部署和运维等方面的知识,不可刚入门就飘起来。另外,文中的代码已上传到码云,感兴趣的欢迎下载交流与学习。

相关推荐
掘根2 小时前
【网络】高级IO——poll版本TCP服务器
网络·数据库·sql·网络协议·tcp/ip·mysql·网络安全
Bear on Toilet3 小时前
初写MySQL四张表:(3/4)
数据库·mysql
无妄啊______3 小时前
mysql笔记9(子查询)
数据库·笔记·mysql
Looooking4 小时前
MySQL 中常用函数使用
数据库·mysql
island13144 小时前
从 InnoDB 到 Memory:MySQL 存储引擎的多样性
数据库·学习·mysql
ZZDICT4 小时前
MySQL 子查询
数据库·mysql
柳鲲鹏5 小时前
编译成功!QT/6.7.2/Creator编译Windows64 MySQL驱动(MinGW版)
开发语言·qt·mysql
一个很帅的帅哥5 小时前
实现浏览器的下拉加载功能(类似知乎)
开发语言·javascript·mysql·mongodb·node.js·vue·express
dbln5 小时前
MySQL之表的约束
数据库·mysql
白总Server6 小时前
MySQL在大数据场景应用
大数据·开发语言·数据库·后端·mysql·golang·php