該項目git地址:https://github.com/ht-sauce/dream-admin前端
慣例:我的的廢話部分vue
我的是前端開發,可是公司有時候比較閒。因此就想着本身寫點東西,老摸魚,太沒意思了,還有一個就是裝逼和加薪。java
後端這塊我比較早之前用過express,本身開發過簡單的後端管理系統。node
最近一年多正式作了開發,一開始我先搭建了個人前端博客頁面(如今想起來是單頁面項目,並不完美,最好是用服務端渲染來開發的)。後面博客系統確定須要有後端因此,繼續用nodejs是沒錯的。我不打算用java,或者go語言之類的。對於我這樣的菜鳥,貪多嚼不爛。並且java是我見過最笨重的語言之一。java的開發很繁瑣,歷史包袱重。新手教程很是不友好。自學難度入門很難。進門以後又容易被不完美的教程帶偏(缺這個少那個)。mysql
java主要緣由是由於早期沒有一個包管理系統(目前的go語言等沒有這個問題),致使了java在包管理上的混亂。致使新手不友好。react
總體項目我是模擬大項目的。git
項目目前分爲四大塊。程序員
博客系統(我的生活展現平臺,記錄平臺)github
會員系統(負責登陸和權限的統一管理,將登陸和人員部分單獨分離)算法
接口管理系統(就是一個接口記錄平臺)
後端管理平臺
想法上很是美好,可是我目前爲止後端纔剛開始搞。前端基本頁面差很少,可是沒有後端的數據配合,寫了總感受缺乏什麼。雖然也能寫啦,可是和後端不一樣,前端我寫了一年多。感受沒有什麼大挑戰了。只是寫的慢和快的問題,加上公司也不必定會有一些我設想中的東西。因此本身寫後端,本身玩。(可是本身仍是很懶,三個月才這麼點)。
express確定不會用了,因此後端我也就剩下koa框架了。(這塊主要是參考招聘網站中經常使用的框架,並且結合市場去學習選型)
koa框架我官網看過,比express好不少。可是koa有種react的感受,什麼都須要本身弄。express也是同樣的。
後面在逛論壇(cnode社區)下,發現cnode基本放棄express使用koa,jest和eggjs框架。其中eggjs是最多的。而後也去官網看了看。
eggjs最大的優勢是他是阿里的,它用於雙十一了。還有eggjs幫初學者和新手繼承了很是多的功能。就像vue腳手架,初始就給你把架子搭建好了。你再也不須要本身去作那些繁瑣的事情,並且是業界大神幫你搭建的。
舉例:
基礎安全機制
日誌系統
多進程負載
等……
其中多進程負載是我很看重的,由於這個新手老手都不必定能搞定。這是nodejs能利用多核cpu的關鍵。
推薦個人這個文章看看,很好的入門視頻教程。下載不了的請留言。我找時間本身上傳百度雲看看。
https://juejin.im/post/5d6c872ae51d4561f64a0862
由於egg對後端的基礎環境作了很是良好的集成。因此咱們再也不須要作繁瑣的初始工做注重開發就好了。可是仍是須要作基礎的選型。主要是數據庫鏈接上。
我說句很差聽的,爲何後端程序員經常會被嘲諷爲增刪改查工程師。甚至是一些後端人員認爲本身很牛逼(實際上只是會增刪改查)。這不懂後端的你們不知道,懂了的會發現。後端入門以後基本上的事情就是鏈接數據庫查詢結果,插入數據,返回數據。就是這麼簡單會sql,甚至是部分代碼只須要複製黏貼就好了。格式整齊劃一。因此後端我認爲主要牛逼在多年經驗和算法。一個初級的後端程序員比前端簡單,可是後端比前端工資高。爲何呢?由於前端沒了後端走不了業務,後端能夠離開前端(簡單的頁面)。其實很是不公平,若是二者分開,初級前端比初級後端強。特別是當下的前端環境。
說了這麼多,其實全部的一切在初級後端下,咱們只須要搞定框架和數據庫鏈接插件就ok了。恩,還有寫接口。
在數據庫上面nodejs目前分爲兩大塊,一個是mongdb和mysql。一個是nosql一個是關係型數據庫。二者我都用過,可是在nosql上我表示本身不夠熟練,還有就是在數據庫建模方面總以爲有問題因此我放棄了。
那麼只有mysql了。
mysql的選擇很少,主要是mysql官方插件和orm插件(sequelize)
比較方面:
egg-mysql:
就是傳統的sql語句,主要缺點是開發人員容易發生數據庫語句拼接,發生sql注入。
egg-sequelize
不少人說性能問題,這個能夠忽略不計。最大問題在於非關係型語句操做。所有是封裝好的對象編寫方式。關鍵在於學習了sql語句以後還須要學習這個。可是不得不說,orm框架簡化了一些sql的編寫問題。
graphql:
很是不喜歡,文檔少,並且繁瑣。總感受目前而已意義不大。雖然很誘人的感受。
基礎的數據庫安裝我就不教了。我用mysql8.X
數據庫鏈接很簡單,egg封裝上都作好了。
先執行
npm install --save egg-sequelize mysql2複製代碼
而後配置數據庫鏈接
\dream-admin\config\plugin.js
'use strict';
/** @type Egg.EggPlugin */
module.exports = {
static: {
enable: true,
},
sequelize: {
enable: true,
package: 'egg-sequelize',
},
};複製代碼
\dream-admin\config\plugin.js\config.default.js
/* eslint valid-jsdoc: "off" */
'use strict';
module.exports = appInfo => {
const config = exports = {
static: { prefix: '/dreamdht/' },
keys: appInfo.name + '_1568770372144_7988',
security: {
csrf: {
ignore: () => true,
},
},
};
config.sequelize = {
dialect: 'mysql', // support: mysql, mariadb, postgres, mssql
database: 'dream',
host: 'localhost',
port: 9906,
username: 'root',
password: '1111',
timezone: '+08:00',
// 時間格式轉化
dialectOptions: {
dateStrings: true,
typeCast: true,
},
};
return config;
};複製代碼
orm框架和傳統數據庫插件相比,多了模型的編寫這一步。至關於數據庫建表,建模。
egg框架全部業務模型都放在app\model文件下面
個人是這樣的
拿出一個模型例子:userInfo
這裏我不作多餘延伸。由於這篇文章主要是記錄數據庫操做的問題。整篇文章涉及不少知識點。每一項都須要很大的精力去閱讀文檔。特別是沒有後端基礎那更加是看不了的。
'use strict';
module.exports = app => {
const { STRING, INTEGER, DATE, ENUM } = app.Sequelize;
const UserInfo = app.model.define('consumer-userInfos', {
userid: {
type: INTEGER,
primaryKey: true,
comment: 'user帳號表id',
},
nickname: {
type: STRING(30),
allowNull: false,
defaultValue: '',
comment: '暱稱',
},
portrait: {
type: STRING(200),
comment: '用戶頭像',
},
sex: {
type: ENUM('男', '女'),
comment: '性別',
},
phone: {
type: STRING(15),
comment: '聯繫電話',
unique: true,
},
birthday: {
type: DATE,
comment: '生日',
},
provinceAndCity: {
type: STRING(30),
comment: '省市區域碼',
},
address: {
type: STRING(100),
comment: '詳細住址',
},
qq: {
type: STRING(100),
comment: 'qq或微信信息',
},
email: {
type: STRING(50),
comment: '郵箱地址',
unique: true,
},
}, { comment: '用戶信息表,每一個用戶惟一' });
return UserInfo;
};複製代碼
這裏同樣說文章主要目的。
下面的語句包含兩部分,一個是sql事務,還有一個是關於現代nodejs框架配合async\await如何處理錯誤。
await ctx.model.Consumer.UserInfo.create(data, { transaction });複製代碼
錯誤的方式:
await ctx.model.Consumer.UserInfo.create(data, transaction );複製代碼
eggjs在錯誤處理上和傳統的後端很像了,主要是靠try\catch捕獲錯誤。
而後我這裏的邏輯調用在於我是控制層訪問——服務層——訪問——數據庫
那麼服務層其實就能捕獲數據庫錯誤了。可是在控制層我同樣是用try\catch來捕獲錯誤。那麼你應該在我下面代碼同樣。用
// 返回錯誤信息
return Promise.reject(e);
// 或throw e;複製代碼
來返回錯誤結果,保證控制層也正常的報錯
直接上代碼:
'use strict';
const Service = require('egg').Service;
class UserService extends Service {
async find() {
const { ctx, app } = this;
const sequelize = app.Sequelize;
const query = [[ sequelize.fn('COUNT', sequelize.col('id')), 'num' ]];
// console.log(result[0].dataValues.num);
return await ctx.model.Consumer.User.findAll({
attributes: query,
});
}
// 建立用戶帳號和用戶信息
async create(data) {
// 獲取當前條目數加1做爲主鍵id
const { ctx, app } = this;
const sequelize = app.Sequelize;
const query = [[ sequelize.fn('COUNT', sequelize.col('id')), 'num' ]];
const count = await ctx.model.Consumer.User.findAll({
attributes: query,
});
const id = count[0].dataValues.num + 1;
data.id = id;
data.userid = id;
let transaction;
try {
// 啓用事務
transaction = await ctx.model.transaction();
// 建立帳號
await ctx.model.Consumer.UserInfo.create(data, { transaction });
await ctx.model.Consumer.User.create(data, { transaction });
// 提交事務
await transaction.commit();
return true;
} catch (e) {
// 錯誤事務回滾
await transaction.rollback();
// 返回錯誤信息
return Promise.reject(e);
}
}
}
module.exports = UserService;複製代碼
文章主要三點:
Sequelize下面事務的使用。格式很標準。
// 啓用事務
transaction = await ctx.model.transaction();
// 建立帳號
sql業務操做
//提交事務
transaction.commit();
當發生錯誤的時候進行回滾
await transaction.rollback();
而後是事務使用的時候注意事項。代碼格式別錯了。
還有就是mysql時區致使查詢出來的結果時間格式不對
感謝eggjs團隊開源框架
參考文章:
sequelize中文文檔:https://demopark.github.io/sequelize-docs-Zh-CN/
參考博客:https://blog.csdn.net/awhlmcyn/article/details/79816494
參考博客:https://blog.csdn.net/clearlxj/article/details/94597734