之前分享了一篇 Nodejs 与 MySQL 数据库交互 的文章,这篇文章主要是讲 mysql模块的使用方式。今天准备分享一篇 Nodejs 服务端 MVC 架构,通过服务端提供的API来完成数据库的CRUD操作。
MVC是一种项目架构思想,即对项目进行分层,不同层负责的职责不同。
M层:model 模型,业务逻辑处理,更多体现的是数据库CRUD;
V 层:view 视图,负责数据的呈现;
C 层:controller 控制器,负责业务流程(V与M之间的沟通桥梁)
MVC在express项目里的体现:
-- 创建数据库(不存在时才创建)
CREATE DATABASE IF NOT EXISTS nodejs_mysql_db DEFAULT CHARSET utf8;
-- 创建users表(不存在时才创建)
CREATE TABLE IF NOT EXISTS `users` (
`id` INT(8) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(10) NOT NULL,
`age` INT(11) DEFAULT NULL,
`sex` VARCHAR(10) DEFAULT NULL,
`status` INT(1) DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
由于我这个项目主要是用于服务端,提供API给前端使用,所以接下来我就省略调了 views 的内容。
项目启动文件
const express = require("express");
const app = express();
const {global} = require("./config/global");
const user = require("./routes/user");
app.use(user);
app.listen(global.port,global.hostname,function (){
console.log('Express server listening at http://%s:%d',global.host,global.port);
})
全局配置文件
exports.global = {
"host":"localhost",
"port":8899
}
数据库配置文件
const mysql = require("mysql");
const pool = mysql.createPool({
host:"localhost",
port:3306,
user:"root",
password:"1234qwer"
})
exports.UserDB = ()=>{
pool.config.connectionConfig.database = "nodejs_mysql_db";
return pool;
}
/*
// 可以通过这种方式,切换不同的DB实例
exports.BookDB = ()=>{
pool.config.connectionConfig.database = "ex_test";
return pool;
}
*/
exports.mysql = mysql;
M层,user业务逻辑处理,主要是数据库的CRUD操作
const DB = require("../config/db");
const UserDB = DB.UserDB();
let DBResult = {};
DBResult.getUserList = function (cb){
UserDB.getConnection(function (err,conn){
if(err){return console.log(err)}
conn.query("SELECT * FROM users",function (error,results){
if(error){return console.log(error)}
console.log(conn.threadId);
conn.release();
cb(results);
})
})
}
DBResult.addUser = function (args,cb){
UserDB.getConnection(function (err,conn){
if(err){return console.log(err)}
// console.log(DB.mysql.format("INSERT INTO users(name,age,sex) VALUES ?",args));
conn.query("INSERT INTO users(name,age,sex) VALUES ?",args,function (error,results){
if(error){return console.log(error)}
console.log(conn.threadId);
conn.release();
cb(results);
})
})
}
DBResult.updateUser = function (args,cb){
UserDB.getConnection(function (err,conn){
if(err){return console.log(err)}
// console.log(DB.mysql.format("UPDATE users SET ? WHERE id = ?",args));
conn.query("UPDATE users SET ? WHERE id = ?",args,function (error,results){
if(error){return console.log(error)}
console.log(conn.threadId);
conn.release();
cb(results);
})
})
}
DBResult.deleteUser = function (args,cb){
UserDB.getConnection(function (err,conn){
if(err){return console.log(err)}
conn.query("DELETE FROM users WHERE id = ?",args,function (error,results){
if(error){return console.log(error)}
console.log(conn.threadId);
conn.release();
cb(results);
})
})
}
module.exports = DBResult;
user路由文件,负责将API请求转发到model/userDao.js,完成数据库的CRUD操作,然后再将查询到的数据库数据返回给接口
const express = require("express");
const user = express.Router();
const userDao = require("../models/userDao");
user.all("*",express.json());
user.get("/users",function (req,res){
userDao.getUserList(function (userList){
res.send(userList);
});
})
user.post("/users",function (req,res){
userDao.addUser([req.body],function (addRes){
res.send(addRes);
})
})
user.put("/users/:id",function (req,res){
userDao.updateUser([req.body,req.params.id],function (updateRes){
res.send(updateRes);
})
})
user.delete("/users/:id",function (req,res){
userDao.deleteUser(req.params.id,function (deleteRes){
res.send(deleteRes);
})
})
module.exports = user;
0. 刚建好的users 表中无任何数据
POST http://localhost:8899/users
GET http://localhost:8899/users
PUT http://localhost:8899/users/1
再调用查询接口,id=1的数据已更新
DELETE http://localhost:8899/users/2
删除id=2的数据后再查询,仅剩id=1的数据
以 POST http://localhost:8899/users 为例
客户端在调用服务端接口后,请求进入app.js,app.use(user) 将请求转发到 routes/user.js 里user.post 方法;
在user.post方法里,调用model/userDao.js的addUser方法;
那么怎么将user.post路由参数传递给 addUser方法,又怎么将addUser方法从数据库拿到的数据返回给user.post呢?
(1)定义addUser方法接收两个参数,一个args参数,一个cb代表的回调函数,conn.query查询完数据库后,执行cb回调函数,将结果返回给调用者。
注意: args 可以是单个参数,也可以是数组,如果没有路由参数,args也可以省略,如
getUserList 方法就只有一个cb回调函数。
// models/userDao.js
DBResult.addUser = function (args,cb){
UserDB.getConnection(function (err,conn){
if(err){return console.log(err)}
conn.query("INSERT INTO users(name,age,sex) VALUES ?",args,function (error,results){
if(error){return console.log(error)}
conn.release();
cb(results);
})
})
}
(2)调用addUser方法时,传递req.body作为args参数,再传一个函数作为回调函数,这个函数也接收一个参数,此参数实际上就对应conn.query里返回的results,然后通过res.send返回给接口
// routes/user.js
user.post("/users",function (req,res){
userDao.addUser([req.body],function (addRes){
res.send(addRes);
})
})
参考资料:
NodeJS整合MySQL