在上一章中,咱們爲後端的express服務設置了跨域訪問,並未前端的angular安裝了bootstrap和ng-bootstrap依賴,並進行了配置,爲後端的express安裝了mysql和處理文件上傳的multiparty依賴並建立了mysql數據庫birthday在這一章中,我準備介紹一下express對mysql數據庫的訪問。html
用visual studio code(如下簡稱爲vs code)打開後端程序目錄server,在server目錄下建立一個db目錄,用於存放路由初始化文件。在db目錄下新建議dbconnpool.js文件,文件中的代碼爲:前端
var mysql = require('mysql'); module.exports = (function(){ var pool = mysql.createPool({ host:'localhost', user:'root', password:'******', database:'birthday', port:'3306' }); pool.on('connection',function(connection){ connection.query('SET SESSION auto_increment_increment=1'); }); return function(){ //返回惟一的一個pool return pool; } })();
這是一個當即執行函數,而且其中的pool對象是一個單例對象,這就保證了全部對數據庫的操做都針對同一個數據庫對象(我是這樣理解的,可能有誤差)。
mysql.createPool(<options>)方法建立了一個mysql訪問池,options是一個參數對象,其中包括了mysql的主機名,登陸mysql用戶名、密碼和須要訪問的數據庫以及端口(默認爲3306)。關於數據庫鏈接池的概念,向你們推薦這個地址,裏面介紹的很詳細。
pool.on('connection',function(conection){...})這個函數是數據庫進行鏈接時的回調函數,在這裏我主要設置了一下自增加型數據的步進值爲1。mysql
打開server目錄下的routers目錄的users.js文件,這是一個express-generator已經構建好的文件,我就用這個文件做爲處理用戶請求的文件。在這個文件中加載了Router 實例,Router是一個完整的中間件和路由系統。用這個中間件,能夠方便的處理全部的路由訪問。另外還要加載咱們剛剛創建的dbconnpool.js文件。web
var express = require('express'); var router = express.Router(); var connPool = require('../db/dbconnpool'); var pool = connPool();
這裏還涉及了jwt用戶認證的處理,做爲用戶註冊,咱們只須要將用戶認證信息發到前端就OK了!我對jwt的使用也不是很精通,只是明白大概的原理和使用方法,在這裏發個原理圖供你們參考。sql
若是你們感興趣,能夠參考這篇文章,這裏介紹的仍是很詳細的。咱們爲了程序的完整性,先將這個中間件安裝並加載進來。在express中使用jwt,須要使用兩個中間件express-jwt和jsonwebtoken,安裝方法:cnpm install express-jwt --save
cnpm install --save jsonwebtoken
在user.js文件中咱們只須要使用jsonwebtoken,讓咱們引入這個文件:var jwt = require('jsonwebtoken');
數據庫
讓咱們開始處理用戶註冊請求吧,下面是代碼:express
router.post('/register', function (req, res, next) { let userName = req.body['name']; let userPass = req.body['password']; let email = req.body['email']; if(userName.length === 0 || userPass.length === 0){ res.status(400).json({ code: '-200', msg: '用戶名或密碼未輸入' }); return; } let params = [userName, userPass, email]; let sqlStr = 'insert into user (uname, upass, uemail)values(?,?,?);' pool.getConnection(function (err, conn) { if (err) { res.status(400).json({ code: '-200', msg: '數據庫鏈接失敗' }); return; } conn.query(sqlStr, params, function (err, rs) { if (err) { if(err.message.includes('Duplicate')){ res.status(400).json({ code: '-200', msg: '註冊用戶出錯:用戶名重複' }); return; }else{ res.status(400).json({ code: '-200', msg: '註冊用戶出錯:' + err.message }); return; } } res.status(200).json({ token: jwt.sign({ userid: rs.insertId }, 'secret') }); }); conn.release(); }); });
咱們把這段代碼分析一下:npm
客戶端用POST方法發送的註冊信息有用戶名(name)、密碼(password)和郵箱地址(email),分別從req.body中取出這3個數據,並分別賦值給userName、userPass、email三個變量。將mysql查詢語句賦值給變量sqlStrlet sqlStr = 'insert into user (uname, upass, uemail)values(?,?,?);'
,
並利用上面賦值的userName、userPass、email變量聲明查詢參數數組params(其實就是爲sql查詢語句的那3個?賦值)。json
調用pool.getConnection()函數鏈接數據庫,在鏈接的回調函數中有連個參數err和conn,err參數包含了在鏈接數據庫時的錯誤信息。若是在鏈接中發生錯誤,能夠經過錯誤處理代碼向客戶端發送錯誤信息,並當即返回。若是沒有錯誤,就能夠對數據庫進行操做了。bootstrap
註冊用戶對數據庫的操做爲插入數據,前邊賦值的sql語句就是標準的sql插入語句,只不過將values的值換成了?,以便利用咱們的params數組中的變量做爲參數。對數據庫進行操做的方法是conn.query()函數,裏面有3個參數,第一個參數是要執行的sql語句,第二個參數是查詢參數,第三個參數是回調函數。
回調函數包括兩個參數,第一個參數一樣是err參數,用於對發生的錯誤進行處理,我把重複註冊同一個用戶的錯誤處理放在了這裏,若是發生重複註冊,mysql會返回一條包含'ER_DUP_ENTRY: Duplicate entry '<username>' for key 'un''的語句,證實你發送到mysql的信息違背了數據的惟一性屬性。根據這個錯誤信息,就能夠對重複註冊用戶進行處理。
第二個參數rs包含了一些新插入的數據信息,其中最重要的一個信息是insertId,這個就是咱們的user id。若是向mysql數據庫插入數據成功,就返回200的狀態信息,並向客戶端發送一個json對象,對象包含一個token鍵,這個鍵對應了用'jsonwebtoken'的sign函數生成的認證信息,信息中包含了從rs中取得的insertId。
最後用conn.release();
釋放掉對數據庫的鏈接。
對登陸請求的處理也很簡單,主要是對數據庫進行查詢操做,找到正確的用戶名和密碼,就發送認證信息,未找到就發送錯誤信息。
具體代碼以下:
router.post('/login', function (req, res, next) { let userName = req.body['name']; let userPass = req.body['password']; let params = [userName, userPass]; let sqlStr = "select * from user where uname=? and upass=?"; pool.getConnection(function(err, conn){ if(err){ res.status(400).json({code:'-200',msg:'數據庫鏈接失敗'}); return; } conn.query(sqlStr, params, function(err,rs){ if(err){ res.status(400).json({ code: '-200', msg: '查詢用戶出錯:' + err.message }); return; } if(rs.length === 0){ res.status(401).json({ code: '-200', msg: '登陸失敗,用戶名或密碼輸入錯誤!'}); return; } res.status(200).json({token: jwt.sign({ userid: rs[0].uid }, 'secret') }); }); conn.release(); }); });
此次在jwt認證信息中的用戶id來自查詢到的uid。
用戶註冊和登陸的express處理程序就是這些了。中間可能還有不太合理的地方,但願你們可以給予指正。今天就寫到這裏了。謝謝你們的關注......