利用angular4和nodejs-express構建一個簡單的網站(三)—express訪問mysql

在上一章中,咱們爲後端的express服務設置了跨域訪問,並未前端的angular安裝了bootstrap和ng-bootstrap依賴,並進行了配置,爲後端的express安裝了mysql和處理文件上傳的multiparty依賴並建立了mysql數據庫birthday在這一章中,我準備介紹一下express對mysql數據庫的訪問。html

對mysql訪問的基本配置

用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

處理用戶發來的註冊用戶請求,並將用戶數據存入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

clipboard.png

若是你們感興趣,能夠參考這篇文章,這裏介紹的仍是很詳細的。咱們爲了程序的完整性,先將這個中間件安裝並加載進來。在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查詢語句賦值給變量sqlStr
let 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處理程序就是這些了。中間可能還有不太合理的地方,但願你們可以給予指正。今天就寫到這裏了。謝謝你們的關注......

相關文章
相關標籤/搜索