亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Express使用mongodb管理會(huì)話儲(chǔ)存 connect-mongo模塊簡(jiǎn)介

jackzou / 707人閱讀

摘要:簡(jiǎn)介在我的前一篇小文中小書提到了可以更換會(huì)話儲(chǔ)存那么這篇文章我們就來講講在進(jìn)行會(huì)話管理的時(shí)候如何將會(huì)話數(shù)據(jù)保存在外部數(shù)據(jù)庫中本文中我們使用用作會(huì)話儲(chǔ)存數(shù)據(jù)庫本文中使用的模塊以及版本號(hào)一覽模塊名稱版本號(hào)特性支持支持所有版本的支持支持

簡(jiǎn)介

在我的前一篇小文中express-session小書提到了express-session可以更換會(huì)話儲(chǔ)存.

那么這篇文章我們就來講講express在進(jìn)行會(huì)話管理的時(shí)候如何將會(huì)話數(shù)據(jù)保存在外部數(shù)據(jù)庫中,本文中我們使用mongodb用作會(huì)話儲(chǔ)存數(shù)據(jù)庫.

本文中使用的模塊以及版本號(hào)一覽:

模塊名稱 版本號(hào)
express 4.16.4
mongodb 3.1.8
express-session 1.15.6
connect-mongo 2.0.3
connect-mongo特性

支持Express5

支持所有版本的Connect

支持Mongoose>=4.1.2+

支持原生Mongodb驅(qū)動(dòng)>=2.0.36

支持Node.js 4 6 8 10

支持Mongodb>=3.0

事前分析

由于mongodb客戶端和服務(wù)器可以是多對(duì)多的關(guān)系,故有如下組合.

一個(gè)客戶端連接多個(gè)服務(wù)器

多個(gè)客戶端連接一個(gè)服務(wù)器

多個(gè)客戶端連接多個(gè)服務(wù)器

一個(gè)客戶端連接一個(gè)服務(wù)器

本文主要講解一個(gè)客戶端連接一個(gè)服務(wù)器.

這種情況下,一般服務(wù)器監(jiān)聽一個(gè)端口,而我們希望可以共享同一個(gè)mongodb驅(qū)動(dòng)的實(shí)例.

但是在一般情況下,我們的mongodb數(shù)據(jù)庫不可能只用于會(huì)話管理任務(wù),所以本文復(fù)用同一個(gè)連接(端口).

只要復(fù)用同一個(gè)連接可以完成,那么使用多帶帶的驅(qū)動(dòng)實(shí)例來用作會(huì)話管理也就不在話下了.

起步

首先我們引入所有的模塊:

const
    Express = require("express")(),
    MongoClient = require("mongodb").MongoClient,
    ExpressSession = require("express-session"),
    MongoStore= require("connect-mongo")(ExpressSession);

看起來connect-mongo需要將express-session包裝一下,這步是固定的.

接下來我們定義幾個(gè)常量用于連接數(shù)據(jù)庫:

const
    UrlOfDb = "mongodb://localhost:27017",
    NameOfDb = "demo",
    Client = new MongoClient(UrlOfDb);// 創(chuàng)建mongodb客戶端

客戶端連接數(shù)據(jù)庫:

Client.connect((error) => {

    if (error) {
        throw error;
    }
    
});

使用一個(gè)數(shù)據(jù)表,并且查詢幾條數(shù)據(jù):

    const
        DataBase = Client.db(NameOfDb),
        Collection = DataBase.collection("sessions");
        
    Collection.find({}).toArray((error, result) => {

        if (error) {
            throw error;
        }
    
        for (const element of result) {
    
            console.log(element);
    
        }

    });

到目前為止我們沒有進(jìn)行session管理,你可以替換本例中的數(shù)據(jù)表名稱用于測(cè)試一下運(yùn)行是否正常.

完整代碼:

const
    Express = require("express")(),
    MongoClient = require("mongodb").MongoClient,// 獲取數(shù)據(jù)庫驅(qū)動(dòng)
    ExpressSession = require("express-session"),// 獲取session中間件
    MongoStore= require("connect-mongo")(ExpressSession);// 獲取session儲(chǔ)存插件
    
const
    UrlOfDb = "mongodb://localhost:27017",
    NameOfDb = "demo",
    Client = new MongoClient(UrlOfDb);// 創(chuàng)建客戶端
    
Client.connect((error) => {

    if (error) {
        throw error;
    }
    
    const
        DataBase = Client.db(NameOfDb),// 獲取數(shù)據(jù)庫
        Collection = DataBase.collection("sessions"); // 獲取數(shù)據(jù)表
    
    // 查詢數(shù)據(jù)表
    Collection.find({}).toArray((error, result) => {

        if (error) {
            throw error;
        }

        for (const element of result) {

            console.log(element);

        }

    });
    
});

現(xiàn)在我們來使用express-session中間件,并且替換掉默認(rèn)的儲(chǔ)存:

// +++++

const
    DataBase = Client.db(NameOfDb),// 獲取數(shù)據(jù)庫
    Collection = DataBase.collection("sessions"),// 獲取數(shù)據(jù)表
    MongoStoreInstance = new MongoStore({ // 創(chuàng)建一個(gè)儲(chǔ)存實(shí)例,傳入db參數(shù)對(duì)于的數(shù)據(jù)庫對(duì)象
        db:DataBase
    });

// 使用中間件
Express.use(ExpressSession({
    secret: "hello mongo",// cookie簽名
    cookie: {maxAge: 1800000},
    rolling:true,
    saveUninitialized:true,
    resave: false,
    store:MongoStoreInstance // 替換掉默認(rèn)的儲(chǔ)存
}));

// +++++++

注意:connect-mongo會(huì)在該database下創(chuàng)建一個(gè)sessions的數(shù)據(jù)表(沒有這個(gè)數(shù)據(jù)表的情況下).

添加一個(gè)路由用于完成簡(jiǎn)單的驗(yàn)證,用于測(cè)試是否正常工作:

Express.get("/",(request,response)=>{

    if(request.session.name){

        response.send(`歡迎回來${request.session.name}`);

        return ;
    }
    
    // 使用查詢字符串當(dāng)作保存的信息
    request.session.name = request.query.name;
    request.session.pwd = request.query.pwd;

    response.send(`歡迎登錄${request.session.name}`);

});

// 啟動(dòng)服務(wù)器
Express.listen(8888, function () {

    console.log("server is listening 8888 port!");

});

完整代碼:

const
    Express = require("express")(),
    MongoClient = require("mongodb").MongoClient,
    ExpressSession = require("express-session"),
    MongoStore= require("connect-mongo")(ExpressSession);


const
    UrlOfDb = "mongodb://localhost:27017",
    NameOfDb = "demo",
    Client = new MongoClient(UrlOfDb);


function destroyDb(Client) {

    return destroyDb = function () {

        const info = "Client has been closed!";

        Client.close();
        Client = null;
        console.log(info);

        return info;

    }
}

Client.connect((error) => {

    if (error) {
        throw error;
    }

    const
        DataBase = Client.db(NameOfDb),
        Collection = DataBase.collection("sessions"),
        MongoStoreInstance = new MongoStore({
            db:DataBase
        });


    Express.use(ExpressSession({
        secret: "hello mongo",
        cookie: {maxAge: 1800000},
        rolling:true,
        saveUninitialized:true,
        resave: false,
        store:MongoStoreInstance
    }));

    // 使用閉包將關(guān)閉數(shù)據(jù)庫掛載到全局
    destroyDb(Client);

    // 展示復(fù)用一個(gè)連接
    Collection.find({}).toArray((error, result) => {

        if (error) {
            throw error;
        }

        for (const element of result) {

            console.log(element);

        }

    });

    Express.get("/",(request,response)=>{

        if(request.session.name){

            response.send(`歡迎回來${request.session.name}`);

            return ;
        }

        request.session.name = request.query.name;
        request.session.pwd = request.query.pwd;

        response.send(`歡迎登錄${request.session.name}`);

    });

    Express.get("/closedatabase",  (request, respnose) => {

        respnose.send(destroyDb());

    });


    Express.listen(8888, function () {

        console.log("server is listening 8888 port!");

    });

});

注意:我沒有刪除數(shù)據(jù)庫表的常規(guī)輸出,在這個(gè)例子啟動(dòng)的時(shí)候,你會(huì)發(fā)現(xiàn)他們共用了同一個(gè)連接,啟動(dòng)的時(shí)候會(huì)先輸出數(shù)據(jù)表中的內(nèi)容.

測(cè)試

在瀏覽器中輸入如下內(nèi)容:

http://localhost:8888/?name=ascll&pwd=123456

瀏覽器輸出:

歡迎登錄ascll

直接再次訪問該頁面:

http://localhost:8888/

瀏覽器輸出:

歡迎回來ascll

此時(shí)在數(shù)據(jù)庫中手動(dòng)查詢后,或者重啟本項(xiàng)目,你會(huì)在控制臺(tái)中發(fā)現(xiàn)上次留下的session記錄:

{ _id: "qbP36wE0nJkvtyNqx_6Amoesjjcsr-sD",
  expires: 2018-12-14T08:27:19.809Z,
  session:
   "{"cookie":{"originalMaxAge":1800000,"expires":"2018-12-14T08:20:21.519Z","httpOnly":true,"path":"/"},"name":"ascll","pwd":"123456"}" }
使用總結(jié)

引入connect-mongoexpress-session然后調(diào)用connect-mongoexpress-sessino傳入

獲取上一步返回的類,然后使用express-session中間件的時(shí)候?qū)τ?b>store選傳入這個(gè)類的實(shí)例對(duì)象

api 創(chuàng)建

Express 4.x, 5.0 and Connect 3.x:

const session = require("express-session");
const MongoStore = require("connect-mongo")(session);
 
app.use(session({
    secret: "foo",
    store: new MongoStore(options)
}));

Express 2.x, 3.x and Connect 1.x, 2.x:

const MongoStore = require("connect-mongo")(express);
 
app.use(express.session({
    secret: "foo",
    store: new MongoStore(options)
}));
連接到MongoDb 使用mongoose
const mongoose = require("mongoose");
 
// 基本使用
mongoose.connect(connectionOptions);
 
app.use(session({
    store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
 
// 建議使用方式,這樣可以復(fù)用連接
const connection = mongoose.createConnection(connectionOptions);
 
app.use(session({
    store: new MongoStore({ mongooseConnection: connection })
}));
使用Mongo原生Node驅(qū)動(dòng)

這種情況下你需要將一個(gè)mongodb驅(qū)動(dòng)的一個(gè)數(shù)據(jù)庫實(shí)例傳遞給connect-mongo.如果數(shù)據(jù)庫沒有打開connect-mongo會(huì)自動(dòng)幫你連接.

/*
    這里有很多種方式來獲取一個(gè)數(shù)據(jù)庫實(shí)例,具體可以參考官網(wǎng)文檔.
*/

app.use(session({
    store: new MongoStore({ db: dbInstance }) // 別忘了MongoStore是connect-mongo傳入express-session后返回的一個(gè)函數(shù)
}));

// 或者也可以使用Promise版本

app.use(session({
    store: new MongoStore({ dbPromise: dbInstancePromise })
}));
通過連接字符串創(chuàng)建一個(gè)連接
// Basic usage
app.use(session({
    store: new MongoStore({ url: "mongodb://localhost/test-app" })
}));
 
// Advanced usage
app.use(session({
    store: new MongoStore({
        url: "mongodb://user12345:foobar@localhost/test-app?authSource=admins&w=1",
        mongoOptions: advancedOptions // See below for details
    })
}));
事件

一個(gè)MongoStore實(shí)例有如下的事件:

事件名稱 描述 回調(diào)參數(shù)
create session創(chuàng)建后觸發(fā) sessionId
touch session被獲取但是未修改 sessionId
update session被更新 sessionId
set session創(chuàng)建后或者更新后(為了兼容) sessionId
destroy session被銷毀后 sessionId

使用我們之前的例子中添加如下的代碼:

// +++
MongoStoreInstance.on("create",(sessionId)=>{
    console.log("create",sessionId);
});

MongoStoreInstance.on("touch",(sessionId)=>{
    console.log("create", sessionId);
});

MongoStoreInstance.on("update",(sessionId)=>{
    console.log("update", sessionId);
});

MongoStoreInstance.on("set",(sessionId)=>{
    console.log("set", sessionId);
});

MongoStoreInstance.on("destroy",(sessionId)=>{
    console.log("destroy", sessionId);
});

// +++

清空cookie后再次運(yùn)行服務(wù)器,多執(zhí)行幾個(gè)操作你就可以看到session的創(chuàng)建以及修改等操作.

session過期處理 基本處理方式

connect-mongo只會(huì)使用配置了過期時(shí)間的cookie,如果沒有設(shè)置則會(huì)創(chuàng)建一個(gè)新的cookie并且使用tll選項(xiàng)來指定過期時(shí)間:

app.use(session({
    store: new MongoStore({
      url: "mongodb://localhost/test-app",
      ttl: 14 * 24 * 60 * 60 // 默認(rèn)過期時(shí)間為14天
    })
}));

注意:用戶的每次訪問都會(huì)刷新過期時(shí)間.

刪除過期session

默認(rèn)情況下connect-mongo使用MongoDB"s TTL collection特性(2.2+)用于自動(dòng)的移出過期的session.但是你可以修改這種行為.

connect-mongo會(huì)在開始的時(shí)候創(chuàng)建一個(gè)TTl索引,前提是你的Mongo db版本在(2.2+)且有權(quán)限執(zhí)行這一操作.

app.use(session({
    store: new MongoStore({
      url: "mongodb://localhost/test-app",
      autoRemove: "native" // Default
    })
}));

注意:這種默認(rèn)的行為不適用于高并發(fā)的情況,這種情況下你需要禁用默認(rèn)模式,然后自行定義TTl索引.

使用兼容模式

如果你使用了Mongodb的老版本或者不希望創(chuàng)建TTL索引,你可以指定一個(gè)間隔時(shí)間讓connect-mongo來刪除這些過期的session.

app.use(session({
    store: new MongoStore({
      url: "mongodb://localhost/test-app",
      autoRemove: "interval",
      autoRemoveInterval: 10 // 單位分鐘
    })
}));
禁用過期session刪除
app.use(session({
    store: new MongoStore({
      url: "mongodb://localhost/test-app",
      autoRemove: "disabled"
    })
}));
session懶更新

如果你使用的express-session版本>=1.10,然后不希望用戶每次瀏覽頁面的時(shí)候或刷新頁面的時(shí)候都要重新保存,你可以限制一段時(shí)間內(nèi)更新session.

app.use(express.session({
    secret: "keyboard cat",
    saveUninitialized: false, // 如果不保存則不會(huì)創(chuàng)建session
    resave: false, // 如果未修改則不會(huì)保存
    store: new MongoStore({
        url: "mongodb://localhost/test-app",
        touchAfter: 24 * 3600 // 指定觸發(fā)間隔時(shí)間 單位秒
    })
}));

通過這樣設(shè)置session只會(huì)在24小時(shí)內(nèi)觸發(fā)1次無論用戶瀏覽多少次頁面或者刷新多少次.修改session除外.

其他選項(xiàng)

collection 指定緩存數(shù)據(jù)表的名字默認(rèn)sessions

fallbackMemory 回退處理默認(rèn)使用MemoryStore進(jìn)行存儲(chǔ)

stringify 默認(rèn)是true,如果為true則序列化和反序列化使用原生的JSON.xxx處理.

serialize 自定義序列化函數(shù)

unserialize 自定義反序列化函數(shù)

transformId 將sessionId轉(zhuǎn)為你想要的任何鍵然后進(jìn)行儲(chǔ)存

暗坑

也不算是暗坑吧,一用有兩點(diǎn):

Mongodb客戶端正常關(guān)閉后connect-mongo會(huì)報(bào)錯(cuò),雖然會(huì)被Express攔截但是這個(gè)模塊沒有提供error事件.

Express中間件必須同步掛載?在我的例子中嘗試異步加載express-session中間件,但是失敗了中間件沒有效果.

connect-mongo模塊npm地址
https://www.npmjs.com/package...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/100056.html

相關(guān)文章

  • Express使用mongodb管理會(huì)話儲(chǔ)存 connect-mongo模塊簡(jiǎn)介

    摘要:簡(jiǎn)介在我的前一篇小文中小書提到了可以更換會(huì)話儲(chǔ)存那么這篇文章我們就來講講在進(jìn)行會(huì)話管理的時(shí)候如何將會(huì)話數(shù)據(jù)保存在外部數(shù)據(jù)庫中本文中我們使用用作會(huì)話儲(chǔ)存數(shù)據(jù)庫本文中使用的模塊以及版本號(hào)一覽模塊名稱版本號(hào)特性支持支持所有版本的支持支持 簡(jiǎn)介 在我的前一篇小文中express-session小書提到了express-session可以更換會(huì)話儲(chǔ)存. 那么這篇文章我們就來講講express在進(jìn)...

    zhangxiangliang 評(píng)論0 收藏0
  • 微信小程序server-2-實(shí)現(xiàn)會(huì)話

    摘要:安裝安裝及其客戶端命令行工具查看版本啟動(dòng)創(chuàng)建目錄,用于數(shù)據(jù)和日志存儲(chǔ)啟動(dòng)注首次啟動(dòng)可能會(huì)花費(fèi)大概時(shí)間可以使用下面的命令來檢查是否啟動(dòng)成功注默認(rèn)監(jiān)聽端口添加用戶登錄本地服務(wù)創(chuàng)建用戶退出安裝模塊實(shí)現(xiàn)小程序的會(huì)話功能 1.安裝MongoDB #安裝 MongoDB及其客戶端命令行工具 yum install mongodb-server mongodb -y #查看版本 mongod --v...

    Eminjannn 評(píng)論0 收藏0
  • node中的session

    摘要:當(dāng)會(huì)話過期或被放棄后,服務(wù)器將終止該會(huì)話。原來中間件生成的是一個(gè)對(duì)象,里面包含了信息。這個(gè)有一個(gè)過期時(shí)間,比如,上面代碼中設(shè)置的是小時(shí)。也就是說,小時(shí)后,這個(gè)在瀏覽器中會(huì)自動(dòng)消失。 前言 在上一篇中node中的cookie,對(duì)cookie進(jìn)行了相關(guān)介紹,本篇將繼續(xù)前行,對(duì)session進(jìn)行說明。 session是什么 session不就是會(huì)話嘛,那什么是會(huì)話呢?會(huì)話是一個(gè)比連接粒度更大...

    yankeys 評(píng)論0 收藏0
  • node中的session

    摘要:當(dāng)會(huì)話過期或被放棄后,服務(wù)器將終止該會(huì)話。原來中間件生成的是一個(gè)對(duì)象,里面包含了信息。這個(gè)有一個(gè)過期時(shí)間,比如,上面代碼中設(shè)置的是小時(shí)。也就是說,小時(shí)后,這個(gè)在瀏覽器中會(huì)自動(dòng)消失。 前言 在上一篇中node中的cookie,對(duì)cookie進(jìn)行了相關(guān)介紹,本篇將繼續(xù)前行,對(duì)session進(jìn)行說明。 session是什么 session不就是會(huì)話嘛,那什么是會(huì)話呢?會(huì)話是一個(gè)比連接粒度更大...

    fredshare 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

jackzou

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<