使用node+mysql进行后端开发
使用koa:
koa2是一个类,所以引入koa后,要创建实例化“对象”,才能使用koa内部封装的方法。

设置监听端口:

处理http请求:
1、http请求处理链
A、通过app.use()注册async异步函数
B、每收到一个http请求,koa就会调用通过app.use()注册的async异步函数,并传入ctx和next参数。
2、koa使用异步方法处理请求

async:异步函数
ctx:是由koa传入的封装了request和response的变量
3、next()
用await next()来调用下一个async函数
4、middleware
我们把每个async函数称为middleware
针对不同的url申请调用不同的异步函数:
底层的处理方式,是通过if判断请求的地址来进行区分的

使用if判断非常麻烦,使用koa-router省略这一个步骤

koa-router只能省略掉if判断的部分,最后要使用app.use()去调用koa-router这个异步函数

同理可以处理post请求
用post请求时,会遇到一个问题:post请求通常会发送一个表单,或者JSON,它作为request的body发送
但无论是Node.js提供的原始request对象,还是koa提供的request对象,都不提供解析request的body的功能!
引入另一个middleware ——koa-bodyparser解析request的body

用var name = ctx.request.body.name || ''拿到表单的name字段,如果该字段不存在,默认值设置为''
随着需要处理的url越来越多,app.js会显得特别的臃肿
在controller文件中集中描写url:
app.js不再放置url的异步函数处理方式
app.js只用于将所有controller文件夹中的url异步函数,引入,并使用app.use为其注册
引入+注册:就两个函数封装这一些功能

进一步简化app.js
将处理引入与注册url异步函数的方法,作为一个
Controller Middleware
进一步封装到controller.js中,去处理controller文件夹中的url异步函数
const fs = require('fs');
// add url-route in /controllers:
function addMapping(router, mapping) {
for (var url in mapping) {
if (url.startsWith('GET ')) {
var path = url.substring(4);
router.get(path, mapping[url]);
console.log(`register URL mapping: GET ${path}`);
} else if (url.startsWith('POST ')) {
var path = url.substring(5);
router.post(path, mapping[url]);
console.log(`register URL mapping: POST ${path}`);
} else if (url.startsWith('PUT ')) {
var path = url.substring(4);
router.put(path, mapping[url]);
console.log(`register URL mapping: PUT ${path}`);
} else if (url.startsWith('DELETE ')) {
var path = url.substring(7);
router.del(path, mapping[url]);
console.log(`register URL mapping: DELETE ${path}`);
} else {
console.log(`invalid URL: ${url}`);
}
}
}
function addControllers(router, dir) {
fs.readdirSync(__dirname + '/' + dir).filter((f) => {
return f.endsWith('.js');
}).forEach((f) => {
console.log(`process controller: ${f}...`);
let mapping = require(__dirname + '/' + dir + '/' + f);
addMapping(router, mapping);
});
}
module.exports = function (dir) {
let
controllers_dir = dir || 'controllers',
router = require('koa-router')();
addControllers(router, controllers_dir);
return router.routes();
};
这样app.js中只需要引入这个middleware,再调用就可以完成url的处理

操作数据库:
ORM技术:Object-Relational Mapping,把关系数据库的表结构映射到js对象上。
ORM框架:Sequelize
数据库配置信息,在使用Sequelize操作MySQL需要放在参数里,告诉函数应该如何做
将其保存在config.js中
var config = {
database: 'test', // 使用哪个数据库
username: 'www', // 用户名
password: 'www', // 口令
host: 'localhost', // 主机名
port: 3306 // 端口号,MySQL默认3306
};
module.exports = config;
1、创建Sequelize对象实例
//引入
const Sequelize = require('sequelize');
const config = require('./config');
//对象实例化
var sequelize = new Sequelize(config.database, config.username, config.password, {
host: config.host,
dialect: 'mysql',
pool: {
max: 5,
min: 0,
idle: 30000
}
});
new Sequelize(database, [username=null], [password=null], [options={}])
//option可选填




2、定义数据模型model让数据库可以创建表
//第一个参数传入名称Pet,默认的表名是Pets
//第二个参数指定列名和数据类型,如果是主键,需要更详细地指定。
//第三个参数是额外的配置,我们传入timestamps: false是为了关闭Sequelize的自动添加timestamp的功能
var Pet = sequelize.define('pet', {
id: {
type: Sequelize.STRING(50),
primaryKey: true
},
name: Sequelize.STRING(100),
gender: Sequelize.BOOLEAN,
birth: Sequelize.STRING(10),
createdAt: Sequelize.BIGINT,
updatedAt: Sequelize.BIGINT,
version: Sequelize.BIGINT
}, {
timestamps: false
});
3、插入数据
promise方式
var now = Date.now();
Pet.create({
id: 'g-' + now,
name: 'Gaffey',
gender: false,
birth: '2007-07-07',
createdAt: now,
updatedAt: now,
version: 0
}).then(function (p) {
console.log('created.' + JSON.stringify(p));
}).catch(function (err) {
console.log('failed: ' + err);
});
await方式
(async () => {
var dog = await Pet.create({
id: 'd-' + now,
name: 'Odie',
gender: false,
birth: '2008-08-08',
createdAt: now,
updatedAt: now,
version: 0
});
console.log('created: ' + JSON.stringify(dog));
})();
4、查询数据
(async () => {
var pets = await Pet.findAll({
where: {
name: 'Gaffey'
}
});
console.log(`find ${pets.length} pets:`);
for (let p of pets) {
console.log(JSON.stringify(p));
}
})();
5、更新数据
如果要更新数据,可以对查询到的实例调用save()方法:
(async () => {
var p = await queryFromSomewhere();
p.gender = true;
p.updatedAt = Date.now();
p.version ++;
await p.save();
})();
6、删除数据
(async () => {
var p = await queryFromSomewhere();
await p.destroy();
})();
直接使用Sequelize虽然可以创建model,但是存在一些问题
混乱,不方便管理,不规范,无法复用
制定一个规范
A、model统一存放在models文件夹中
B、其次,每一个Model必须遵守一套规范:
- 统一主键,名称必须是
id,类型必须是STRING(50); - 主键可以自己指定,也可以由框架自动生成(如果为null或undefined);
- 所有字段默认为
NOT NULL,除非显式指定; - 统一timestamp机制,每个Model必须有
createdAt、updatedAt和version,分别记录创建时间、修改时间和版本号。其中,createdAt和updatedAt以BIGINT存储时间戳,最大的好处是无需处理时区,排序方便。version每次修改时自增。
这一套规范,不需要去记忆,而是通过一个db.js统一Model的定义:
const Sequelize = require('sequelize');
console.log('init sequelize...');
var sequelize = new Sequelize('dbname', 'username', 'password', {
host: 'localhost',
dialect: 'mysql',
pool: {
max: 5,
min: 0,
idle: 10000
}
});
const ID_TYPE = Sequelize.STRING(50);
function defineModel(name, attributes) {
var attrs = {};
for (let key in attributes) {
let value = attributes[key];
if (typeof value === 'object' && value['type']) {
value.allowNull = value.allowNull || false;
attrs[key] = value;
} else {
attrs[key] = {
type: value,
allowNull: false
};
}
}
attrs.id = {
type: ID_TYPE,
primaryKey: true
};
attrs.createdAt = {
type: Sequelize.BIGINT,
allowNull: false
};
attrs.updatedAt = {
type: Sequelize.BIGINT,
allowNull: false
};
attrs.version = {
type: Sequelize.BIGINT,
allowNull: false
};
return sequelize.define(name, attrs, {
tableName: name,
timestamps: false,
hooks: {
beforeValidate: function (obj) {
let now = Date.now();
if (obj.isNewRecord) {
if (!obj.id) {
obj.id = generateId();
}
obj.createdAt = now;
obj.updatedAt = now;
obj.version = 0;
} else {
obj.updatedAt = Date.now();
obj.version++;
}
}
}
});
}
怎么调用呢db.js创建model?举个例子!
//引入db.js
const db = require('../db');
//调用db.js中的defineModel,定义并暴露model
module.exports = db.defineModel('users', {
email: {
type: db.STRING(100),
unique: true
},
passwd: db.STRING(100),
name: db.STRING(100),
gender: db.BOOLEAN
});
在使用model进行数据库操作时候,每一次都要导入model,如果同时使用多个model,还要写多条语句去导入,显得特别麻烦
创建一个model.js自动化导入所有的model
const fs = require('fs');
const db = require('./db');
let files = fs.readdirSync(__dirname + '/models');
let js_files = files.filter((f)=>{
return f.endsWith('.js');
}, files);
module.exports = {};
for (let f of js_files) {
console.log(`import model from file ${f}...`);
let name = f.substring(0, f.length - 3);
module.exports[name] = require(__dirname + '/models/' + f);
}
module.exports.sync = () => {
db.sync();
};
使用model.js
//引入model.js
const model = require('./model');
//掉用导入
let
Pet = model.Pet,
User = model.User; var pet = await Pet.create({ ... });
使用node+mysql进行后端开发的更多相关文章
- 招聘前端、Java后端开发、测试、Mysql DBA
公司介绍: http://www.lagou.com/gongsi/43095.html http://www.yamichu.com 简历发到: zhuye@yamichu.com 招聘职位: JA ...
- Python后端开发要求
关于Python后端开发要求 一.对Python有兴趣,熟悉Python(标准库) 最好阅读过源码 了解Python的优化(熟悉pypy更佳) 二.至少至少一门语言(不说"精通") ...
- Node.js 从零开发 web server博客项目[登录]
web server博客项目 Node.js 从零开发 web server博客项目[项目介绍] Node.js 从零开发 web server博客项目[接口] Node.js 从零开发 web se ...
- web前端开发和后端开发有什么区别?
web前端分为网页设计师.网页美工.web前端开发工程师 首先网页设计师是对网页的架构.色彩以及网站的整体页面代码负责 网页美工只针对UI这块儿的东西,比如网站是否做的漂亮 web前端开发工程师是负责 ...
- 快速使用node.js进行web开发
首先关于node.js的学习,这里推荐一本比较好的教程,nodejs web开发指南,该书通俗易懂地将node.js语言特性讲解完之后,又从一个项目角度带领读者使用node.js学习web开发.相信这 ...
- 后端开发实践——Spring Boot项目模板
在我的工作中,我从零开始搭建了不少软件项目,其中包含了基础代码框架和持续集成基础设施等,这些内容在敏捷开发中通常被称为"第0个迭代"要做的事情.但是,当项目运行了一段时间之后再来反 ...
- .net core webapi 前后端开发分离后的配置和部署
背景:现在越来越多的企业都采用了在开发上前后端分离,前后端开发上的分离有很多种,那么今天,我来分享一下项目中得的前后端分离. B/S Saas 项目:(这个项目可以理解成个人中心,当然不止这么点功能 ...
- 微信小程序后端开发(Java语言)笔记
前言: 因为是第一次真正接触后端开发,从编码到部署服务器到上线,所以做个笔记,也供和我一样的开发小白一些参考. 一.前期工作:开发环境与工具: 1. 编程语言:Java #笔者还没学PHP,只想 ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十四 ║ VUE 计划书 & 我的前后端开发简史
---新内容开始--- 番外 大家周一好呀,又是元气满满的一个周一呀!感谢大家在周一这个着急改Bug的黄金时期,抽出时间来看我的博文哈哈哈,时间真快,已经到第十四篇博文了,也很顺顺(跌跌)利利 (撞撞 ...
随机推荐
- 【数据分析】算法+Echarts小练
''' 处理逻辑: 按number去处理 先遍历所有的number挨个去找有没有在列表里的,在列表里的拿出另外一个append 把number去除的列表 ''' li = [] with open(r ...
- 小白学习Spark系列六:Spark调参优化
前几节介绍了下常用的函数和常踩的坑以及如何打包程序,现在来说下如何调参优化.当我们开发完一个项目,测试完成后,就要提交到服务器上运行,但运行不稳定,老是抛出如下异常,这就很纳闷了呀,明明测试上没问题, ...
- vue 函数配置项watch以及函数 $watch 源码分享
Vue双向榜单的原理 大家都知道Vue采用的是MVVM的设计模式,采用数据驱动实现双向绑定,不明白双向绑定原理的需要先补充双向绑定的知识,在watch的处理中将运用到Vue的双向榜单原理,所以 ...
- 训练1-P
一个矩形的面积为S,已知该矩形的边长都是整数,求所有满足条件的矩形中,周长的最小值. 例如:S = 24,那么有{1 24} {2 12} {3 8} {4 6}这4种矩形,其中{4 6}的周长最小, ...
- Code VS 1002 搭桥
题目描述 Description 有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点相联系,则它们属于同一座建筑物.现在想在这些建筑物之间搭建一些桥梁,其中桥梁只能沿着矩形的方格的边沿搭建 ...
- Tarjan算法 (强联通分量 割点 割边)
变量解释: low 指当前节点在同一强连通分量(或环)能回溯到的dfn最小的节点 dfn 指当前节点是第几个被搜到的节点(时间戳) sta 栈 vis 是否在栈中 ans 指强连通分量的数量 top ...
- 3.3、Ansible命令参数详解
0.ansible 命令参数详解: [root@localhost ~]# ansible Usage: ansible <host-pattern> [options] Options: ...
- Python之Mail编程
# Mail编程- 管理程序 - Euroda使邮件普及 - Netscape,outlook,forxmail后来居上 - Hotmail使用浏览器发送邮件 ## 邮件工作流程- MUA邮件用户代理 ...
- 【CodeForces 987C】Three displays
[链接] 我是链接,点我呀:) [题意] [题解] 动态规划 设dp[i][j]表示前i个数字,选了j个的最小花费. dp[i][j] = min(dp[k][j-1]+b[i]);//其中a[i]& ...
- 【codeforces 807D】Dynamic Problem Scoring
[题目链接]:http://codeforces.com/contest/807/problem/D [题意] 给出n个人的比赛信息; 5道题 每道题,或是没被解决->用-1表示; 或者给出解题 ...