国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Express使用mongodb管理會話儲存 connect-mongo模塊簡介

jackzou / 642人閱讀

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

簡介

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

那么這篇文章我們就來講講express在進行會話管理的時候如何將會話數據保存在外部數據庫中,本文中我們使用mongodb用作會話儲存數據庫.

本文中使用的模塊以及版本號一覽:

模塊名稱 版本號
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驅動>=2.0.36

支持Node.js 4 6 8 10

支持Mongodb>=3.0

事前分析

由于mongodb客戶端和服務器可以是多對多的關系,故有如下組合.

一個客戶端連接多個服務器

多個客戶端連接一個服務器

多個客戶端連接多個服務器

一個客戶端連接一個服務器

本文主要講解一個客戶端連接一個服務器.

這種情況下,一般服務器監聽一個端口,而我們希望可以共享同一個mongodb驅動的實例.

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

只要復用同一個連接可以完成,那么使用多帶帶的驅動實例來用作會話管理也就不在話下了.

起步

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

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

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

接下來我們定義幾個常量用于連接數據庫:

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

客戶端連接數據庫:

Client.connect((error) => {

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

使用一個數據表,并且查詢幾條數據:

    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);
    
        }

    });

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

完整代碼:

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

    if (error) {
        throw error;
    }
    
    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);

        }

    });
    
});

現在我們來使用express-session中間件,并且替換掉默認的儲存:

// +++++

const
    DataBase = Client.db(NameOfDb),// 獲取數據庫
    Collection = DataBase.collection("sessions"),// 獲取數據表
    MongoStoreInstance = new MongoStore({ // 創建一個儲存實例,傳入db參數對于的數據庫對象
        db:DataBase
    });

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

// +++++++

注意:connect-mongo會在該database下創建一個sessions的數據表(沒有這個數據表的情況下).

添加一個路由用于完成簡單的驗證,用于測試是否正常工作:

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.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
    }));

    // 使用閉包將關閉數據庫掛載到全局
    destroyDb(Client);

    // 展示復用一個連接
    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!");

    });

});

注意:我沒有刪除數據庫表的常規輸出,在這個例子啟動的時候,你會發現他們共用了同一個連接,啟動的時候會先輸出數據表中的內容.

測試

在瀏覽器中輸入如下內容:

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

瀏覽器輸出:

歡迎登錄ascll

直接再次訪問該頁面:

http://localhost:8888/

瀏覽器輸出:

歡迎回來ascll

此時在數據庫中手動查詢后,或者重啟本項目,你會在控制臺中發現上次留下的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"}" }
使用總結

引入connect-mongoexpress-session然后調用connect-mongoexpress-sessino傳入

獲取上一步返回的類,然后使用express-session中間件的時候對于store選傳入這個類的實例對象

api 創建

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 })
}));
 
// 建議使用方式,這樣可以復用連接
const connection = mongoose.createConnection(connectionOptions);
 
app.use(session({
    store: new MongoStore({ mongooseConnection: connection })
}));
使用Mongo原生Node驅動

這種情況下你需要將一個mongodb驅動的一個數據庫實例傳遞給connect-mongo.如果數據庫沒有打開connect-mongo會自動幫你連接.

/*
    這里有很多種方式來獲取一個數據庫實例,具體可以參考官網文檔.
*/

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

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

app.use(session({
    store: new MongoStore({ dbPromise: dbInstancePromise })
}));
通過連接字符串創建一個連接
// 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
    })
}));
事件

一個MongoStore實例有如下的事件:

事件名稱 描述 回調參數
create session創建后觸發 sessionId
touch session被獲取但是未修改 sessionId
update session被更新 sessionId
set session創建后或者更新后(為了兼容) 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后再次運行服務器,多執行幾個操作你就可以看到session的創建以及修改等操作.

session過期處理 基本處理方式

connect-mongo只會使用配置了過期時間的cookie,如果沒有設置則會創建一個新的cookie并且使用tll選項來指定過期時間:

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

注意:用戶的每次訪問都會刷新過期時間.

刪除過期session

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

connect-mongo會在開始的時候創建一個TTl索引,前提是你的Mongo db版本在(2.2+)且有權限執行這一操作.

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

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

使用兼容模式

如果你使用了Mongodb的老版本或者不希望創建TTL索引,你可以指定一個間隔時間讓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,然后不希望用戶每次瀏覽頁面的時候或刷新頁面的時候都要重新保存,你可以限制一段時間內更新session.

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

通過這樣設置session只會在24小時內觸發1次無論用戶瀏覽多少次頁面或者刷新多少次.修改session除外.

其他選項

collection 指定緩存數據表的名字默認sessions

fallbackMemory 回退處理默認使用MemoryStore進行存儲

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

serialize 自定義序列化函數

unserialize 自定義反序列化函數

transformId 將sessionId轉為你想要的任何鍵然后進行儲存

暗坑

也不算是暗坑吧,一用有兩點:

Mongodb客戶端正常關閉后connect-mongo會報錯,雖然會被Express攔截但是這個模塊沒有提供error事件.

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100056.html

相關文章

  • Express使用mongodb管理會話儲存 connect-mongo模塊簡介

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

    zhangxiangliang 評論0 收藏0
  • 微信小程序server-2-實現會話

    摘要:安裝安裝及其客戶端命令行工具查看版本啟動創建目錄,用于數據和日志存儲啟動注首次啟動可能會花費大概時間可以使用下面的命令來檢查是否啟動成功注默認監聽端口添加用戶登錄本地服務創建用戶退出安裝模塊實現小程序的會話功能 1.安裝MongoDB #安裝 MongoDB及其客戶端命令行工具 yum install mongodb-server mongodb -y #查看版本 mongod --v...

    Eminjannn 評論0 收藏0
  • node中的session

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

    yankeys 評論0 收藏0
  • node中的session

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

    fredshare 評論0 收藏0

發表評論

0條評論

jackzou

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<