Node.js + Express + MongoDB實現(xiàn)簡易的CRUD

Express是一個極簡的Node.js Web框架。Express官網(wǎng)

學習了express之后,簡單實現(xiàn)了一個CRUD demo,整理了一些核心點和第三方中間件的使用。

  1. 引入express,啟動一個服務(wù)
const express = require('express');

const app = express();

app.listen(3000, () => {
    console.log('runing...')
})
  1. 托管靜態(tài)文件

對于諸如image、css、js等靜態(tài)資源,Express內(nèi)置了一個 express.static 中間件函數(shù)。

express.static(root, options);
/**
 *  1. 參數(shù)1:靜態(tài)文件根目錄
 *  2. 參數(shù)2:可選配置項 具體參考 http://www.expressjs.com.cn/4x/api.html#express.static
 * /

比如通過這行代碼就可以訪問static目錄下的靜態(tài)文件

app.use(express.static('static'));
http://127.0.0.1:3000/image/dog.png
http://127.0.0.1:3000/css/common.css
...

如果使用多個靜態(tài)資源目錄,則多次調(diào)用即可。

如果為express.static函數(shù)所托管的文件創(chuàng)建虛擬路徑前綴(這個路徑前綴實際上在文件系統(tǒng)中不存在),請指定靜態(tài)目錄的掛載路徑,如下:

app.use('/static', express.static('static'))

就可以通過帶有static前綴的路徑來訪問static靜態(tài)目錄中的資源了。如:

http://127.0.0.1:3000/static/image/dog.png
http://127.0.0.1:3000/static/css/common.css
...
  1. 路由的使用
app.METHOD(path, callback);

如:

app.get('/', (req, res) => {})

app.post('/user', (req, res) => {})

實際開發(fā)中不會把路由全部掛載在app上,不但不易于維護,而且違背了模塊化開發(fā)的思想。Express提供了一個Router函數(shù),用于創(chuàng)建路由實例(容器),作為一個中間件函數(shù),掛載到app上。

// 創(chuàng)建路由容器
const router = express.Router();

roouter.get('/', (req, res) => {})
router.post('/user', (req, res) => {})
// 亦可以鏈式調(diào)用

app.use(router)
  1. body-parser第三方庫用于獲取客戶端post提交的數(shù)據(jù)

    npm i body-parser
    
    • 配置
    const bodyParser = require('body-parser');
    
    // body-parser配置
    // parse application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({ extended: false }))
    // parse application/json
    app.use(bodyParser.json())
    
    • 獲取post提交的數(shù)據(jù)
    req.body
    
  2. 模板引擎使用art-template

    • 安裝
    npm install --save art-template
    npm install --save express-art-template
    
    • 配置
    // 模板引擎配置 默認去views目錄下查找
    
    app.engine('html', require('express-art-template')); // 參數(shù)1:模板的后綴
    
    app.set('view options', {
        debug: process.env.NODE_ENV !== 'production'
    });
    
    • 使用
    res.render(view [, locals] [, callback])
    /* 1. view 模板名
    *  2. 模板需要的數(shù)據(jù)
    *  3. 回調(diào),兩個參數(shù), err 和 html(渲染好的字符串)
    * /
    

    例:

    router.get('/user', (req, res) => {
         res.render('index.html', {
             userInfo: {
                 name: 'Jack',
                 age: 12
            }
        }, (err, html) => {
            if (err) thorw err;
        })
    })
    
  3. md5加密
    使用md5對用戶注冊和登錄的密碼進行加密

    npm i md5
    
    const md5 = require('md5');
    
    // 采用二次加密,生產(chǎn)中一般會在第一次加密后拼接sign以提高安全性
    password = md5(md5(password) + 'userManage');
    
  4. 保存登錄和注冊狀態(tài)
    用戶注冊和登錄后均跳轉(zhuǎn)到首頁,并保存登錄狀態(tài),使用 express-session是針對express的一個中間件

    npm i express-session
    
    • session 配置
    app.use(session({
        // 配置加密字符串,會在原有加密的基礎(chǔ)上,拼接起來再次加密;目的是防止客戶端惡意篡改,提高安全性
        secret: 'keyboard cat',
        resave: false,
    
        // 無論是否需要 session,默認給客戶端分配session,如果設(shè)置成false,只有服務(wù)端設(shè)置了session的時候才會給客戶端分配session
        saveUninitialized: true,
        cookie: {
            // 設(shè)置cookie的過期時間
            maxAge: 1000 * 10
        }
    }))
    

    通過req.session.xxx來獲取設(shè)設(shè)置session;

    注意:

    session默認存儲在內(nèi)存,服務(wù)器一旦重啟就會丟失,真正在生產(chǎn)環(huán)境session采用持久化存儲。

    • 清除session:
    req.session.XXX = null;
    
  5. 統(tǒng)一處理404和500
    處理404的中間件在 app.use(router) 之后,因為只有router上掛載的所有路由都匹配不到的時候才會執(zhí)行404中間件。

    app.use((req, res) => {
        res.render('error/404.html')
    })
    

    基本上每個接口都會考慮500的情況,而且每次的處理邏輯都是一樣的,所以通過中間件統(tǒng)一處理。全局處理錯誤中間件,在需要的地方調(diào)用 next() 傳入 err 對象,則會默認查找具有四個參數(shù)的中間件,并執(zhí)行相應(yīng)的回調(diào)

    app.use((err, req, res, next) => {
        res.status(500).json({
            code: 500,
            msg: err.msg
        })
    })
    
  6. 數(shù)據(jù)庫
    數(shù)據(jù)庫使用第三方庫 mongoose

    npm i mongoose
    

    使用:

    • 加載模塊
    const mongoose = require('mongoose');
    
    
    • 連接數(shù)據(jù)庫
      沒有userManage 數(shù)據(jù)庫的話會自動創(chuàng)建,并且如果沒有數(shù)據(jù) 執(zhí)行show dbs的時候不會顯示該數(shù)據(jù)庫,當有了數(shù)據(jù)后就會顯示
    mongoose.connect('mongodb://localhost/userManage');
    
    • 設(shè)計表結(jié)構(gòu)

    MongoDB 是動態(tài)的,通過代碼來設(shè)計數(shù)據(jù)庫表結(jié)構(gòu),靈活性還是很強的

    const UserManageSchema = new Schema({
        userName: {
            type: String,
            required: true,
            default: ''
        },
        age: {
            type: Number,
            required: true
        },
        gender: {
            type: Number,
            required: true,
            enum: [0, 1]
        },
        birthday: {
            type: String
        },
        job: {
            type: String
        },
        describe: {
            type: String
        }
    })
    
    • 創(chuàng)建構(gòu)造器模型 即集合

    比如: 創(chuàng)建用戶表

    const UserManage = mongoose.model('userManage', UserManageSchema);
    // 參數(shù)1 為集合名,會轉(zhuǎn)換成小寫復(fù)數(shù)的形式,即usermanages MangOOSE自動尋找模型名稱的復(fù)數(shù)版本 
    // 參數(shù)2為集合的架構(gòu)
    
    • 新增數(shù)據(jù)
      新增數(shù)據(jù)需要創(chuàng)建集合的實例,傳入要新增的數(shù)據(jù)對象,調(diào)用save方法。
    new UserManage(DATA).save((err, data) => {}) // data為插入后的數(shù)據(jù),帶數(shù)據(jù)庫生成的主鍵 _id
    
    • 查、改、刪通過集合直接調(diào)用對應(yīng)的方法即可
      以查為例:以郵箱或者昵稱為條件
    UserManage.findOne({
        $or: [
            {email},
            {nickName}
        ]
    }, (err, data) => {
        if (err) return res.status(500).send('server error');
        return res.send(data);
    }) 
    

服務(wù)端重定向只針對同步請求,對異步請求無效。

項目demo移步這里 github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容