跟我一起练--用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应用程序。掌握这些了技能,你已经向全栈开发迈进了一步,如果想在全栈的道路上走得更远,还需要学习消息队列,微服务架构,性能优化,部署和运维等方面的知识,不可刚入门就飘起来。另外,文中的代码已上传到码云,感兴趣的欢迎下载交流与学习。

相关推荐
新知图书10 分钟前
MySQL用户授权、收回权限与查看权限
数据库·mysql·安全
文城52120 分钟前
Mysql存储过程(学习自用)
数据库·学习·mysql
沉默的煎蛋27 分钟前
MyBatis 注解开发详解
java·数据库·mysql·算法·mybatis
C语言扫地僧44 分钟前
MySQL 事务及MVCC机制详解
数据库·mysql
小镇cxy1 小时前
MySQL事物,MVCC机制
数据库·mysql
雾里看山2 小时前
【MySQL】 库的操作
android·数据库·笔记·mysql
꧁瀟洒辵1恛꧂2 小时前
从新手到高手的蜕变:MySQL 视图进阶全攻略
数据库·mysql
doubt。14 小时前
【BUUCTF】[RCTF2015]EasySQL1
网络·数据库·笔记·mysql·安全·web安全
小辛学西嘎嘎15 小时前
MVCC在MySQL中实现无锁的原理
数据库·mysql
咩咩大主教18 小时前
Go语言通过Casbin配合MySQL和Gorm实现RBAC访问控制模型
mysql·golang·鉴权·go语言·rbac·abac·casbin