前言

之前分享了一篇 Nodejs 与 MySQL 数据库交互 的文章,这篇文章主要是讲 mysql模块的使用方式。今天准备分享一篇 Nodejs 服务端 MVC 架构,通过服务端提供的API来完成数据库的CRUD操作。

MVC 介绍

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 的内容。

1. app.js

项目启动文件

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);
})

2. config/global.js

全局配置文件

exports.global = {"host":"localhost","port":8899
}

3. config/db.js

数据库配置文件

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;

4. models/userDao.js

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;

5. routes/user.js

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 表中无任何数据

1. 新增数据

POST http://localhost:8899/users

2. 查询数据

GET http://localhost:8899/users

3. 更新数据

PUT http://localhost:8899/users/1

再调用查询接口,id=1的数据已更新

4. 删除数据

DELETE http://localhost:8899/users/2

删除id=2的数据后再查询,仅剩id=1的数据

关键代码分析

以 POST http://localhost:8899/users 为例

  1. 客户端在调用服务端接口后,请求进入app.js,app.use(user) 将请求转发到 routes/user.js 里user.post 方法;

  1. 在user.post方法里,调用model/userDao.js的addUser方法;

  1. 那么怎么将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

Nodejs 服务端MVC架构相关推荐

  1. nodejs服务端MVC架构介绍

    nodejs服务端MVC架构介绍 MVC架构本质:确定每一个js文件的职责 以nodejs数据管理系统为例,本文章代码仅为服务端演示代码,单独复制粘贴可能无效果.因为MVC并不是一门技术,而是一种项目 ...

  2. 浅谈游戏服务端开发-架构

    网络游戏程序分为客户端和服务端.客户端负责图形渲染.交互和一些简单校验处理,服务端负责业务逻辑处理.数据存储. 我们开发一个游戏demo,服务端程序可以是一个单线程的服务进程.它包含网络通信.业务逻辑 ...

  3. 服务端监控架构设计与实践

    作者:vivo互联网服务器团队-Deng Haibo 一.业务背景 当今时代处在信息大爆发的时代,信息借助互联网的潮流在全球自由的流动,产生了各式各样的平台系统和软件系统,越来越多的业务也会导致系统的 ...

  4. github nodejs mysql_GitHub - lizhuohaicode/express: nodejs服务端开发(Express+Mysql)---小k博客...

    nodejs服务端开发(Express+Mysql) 项目展示 git clone git@github.com:htmlk/express.git 2.再导入express.sql到数据库,数据库名 ...

  5. 微信小程序初见+nodejs服务端 (一个简单的博客)

    推荐网址: 腾讯云快速开发(nodejs前后端):https://developers.weixin.qq.com/miniprogram/dev/qcloud/qcloud.html#%E5%AF% ...

  6. Nodejs服务端编程基础

    为什么要学习后端编程: 目前市场上的需求,要求前端人员掌握后端编程   方便和后端开发人员进行交互   能独立开发完整系统,成为全栈工程师 后端编程做什么: 根据客户端请求,处理业务逻辑, 响应用户数 ...

  7. web服务端的架构演变

    此文已由作者肖凡授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 最近Lofter项目碰到很多性能上的问题,特别是数据库相关的,每次推送后,告警就会第一时间到来.这些问题随着产 ...

  8. IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?

    1.前言 一个完善的IM系统中通常充斥着大量的图片内容,包括:用户头像.图片消息.相册.图片表情等等,那么在做服务端架构设计时该如何存储这些图片呢? 本文分享的是典型Web应用中大量图片的服务端存储加 ...

  9. 使用Node搭建reactSSR服务端渲染架构

    如题:本文所讲架构主要用到技术栈有:Node, Express, React, Mobx, webpack4, ES6, ES7, axios, ejs,  log4js, scss,echarts, ...

最新文章

  1. 车载网络处理器带来多功能能力
  2. 设置行间距_[EndNote]如何修改文末参考文献行间距?
  3. node-mongoDB
  4. 最简单的 java 防反编译技巧
  5. linux 关闭防火墙firewall,centos中关闭防火墙(firewall)及SELinux
  6. SRE(Simple Rule Engine) Document
  7. java中对象多态时成员变量,普通成员函数及静态成员函数的调用情况
  8. 请写一个函数,实现以下功能: 字符串“open_door” 转换成 “OpenDoor”、”make_by_id” 转换成 ”MakeById”...
  9. 深度学习行人重识别ReID最新综述与展望
  10. 《深入探索C++对象模型》笔记之第一章关于对象
  11. python符号表_根据第一个字符分割列表-Python
  12. PyCharm 2020安装(免费版)
  13. 对PNG图像进行编码 Encoding the PNG image
  14. 用python开发的运维管理系统_python运维开发常用模块(一)psutil
  15. 如何去除 录像开始和结束时 的噔噔噔噔声音
  16. cf显示服务器登录,cf显示与服务器
  17. foxmail皮肤_确实很棒!Foxmail 7.1邮箱客户端体验
  18. 机器学习--特征降维方法总结
  19. Opengl入门基础-shader着色器画方形并且填颜色
  20. 大一寒假培训(七)——队列与优先队列

热门文章

  1. 罗克韦尔自动化收购工业自动化系统模拟与仿真的领先软件开发商Emulate3D
  2. 零基础学Python--机器学习(一):人工智能与机器学习概述
  3. 0x80073712_win10更新 错误代码: (0x80073712)
  4. 快速获取一个网站的所有资源,图片,html,css,js......扒站,仿站必备工具
  5. oracle linux下开放1521端口
  6. 扫描器可发现远程服务器,服务器扫描发现漏洞-可通过HTTP获取远端WWW服务信息...
  7. Ubuntu 命令行下浏览网页
  8. CV中一些常见的特征点
  9. Excel把符合条件的数据全部提取出来
  10. 【矩阵论】04——线性空间——子空间