.net core 3.0 Signalr - 08 業務實現-客戶端demo

因爲signalr做爲一個單獨的推送系統,跟業務系統是分離開的,因此此處模擬一個業務系統,新建一個.net core app項目html

模擬實現一個登陸功能

咱們的登陸很簡單,當進入系統,若是檢測到用戶未登陸則跳轉到登陸頁面,用戶只須要輸入用戶名點擊登陸即算登陸成功前端

  • 配置ConfigServices方法 查看代碼vue

    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, cookieOption =>
    {
        cookieOption.LoginPath = "/Account/Login";
        cookieOption.AccessDeniedPath = "/Account/Login";
    });
  • 配置Config方法,配置認證、受權的請求管道 查看代碼git

    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
  • 接收登陸的post請求,寫cookie,跳轉 查看代碼

前端頁面實現

首先在Layout頁面引入須要的js文件(vue、signalr、msgpack五、signalr-protocol-msgpack) 查看代碼github

封裝signalr鏈接相關js

signalr客戶端js的操做就是,建立鏈接、監聽推送,封裝後端js以下 查看代碼ajax

/**
 * 初始化鏈接
 * @param {object} option 參數
 * @param {string} option.url 鏈接的url地址
 * @param {string} option.loggingLevel 日誌級別,默認爲 Error
 * @param {number} option.delay 延遲鏈接 默認爲3000毫秒
 * @param {function} option.onStarted 啓動時觸發
 * @param {function} option.onLine 啓動時觸發
 * @param {function} option.offLine 啓動時觸發
 * @returns {object} 鏈接的實例
 */
function initSignalr(option) {
    var config = Object.assign(true, {
        loggingLevel: signalR.LogLevel.Error,
        delay: 3000,
        url: ''
    }, option);

    var connection = new signalR.HubConnectionBuilder()
        .configureLogging(config.loggingLevel)
        .withUrl(config.url, {
            accessTokenFactory: option.accessTokenFactory
        })
        .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
        .withAutomaticReconnect([0, 2000, 5000, 10000, 20000])
        .build();

    connection.onreconnecting(function (info) {
        console.info('----------------------------------signalr-- onreconnecting', info);
    });

    connection.onclose(function (err) {
        console.info('--------------------------------signalr-- onclose', err);
    });

    connection.on('OnNotify', config.onNotify);

    connection.on('OnLine', config.onLine);

    connection.on('OffLine', config.offLine);

    setTimeout(function () {
        connection.start().then(function (data) {
            option.onStarted && option.onStarted(data);
        }).catch(function (error) {
            console.error(error.toString());
        });
    }, option.delay);

    return connection;
}

調用封裝的js初始化鏈接 查看代碼

  • 而後在Home/Index.cshtml中引入上面的js
  • 在頁面加載完後,調用初始化(案例中使用了vue)

在進入頁面後會彈窗讓用戶輸入加入的組,能夠不輸入也能夠多個segmentfault

function initConnect() {
  $("#collectionUserInfo").modal({
      keyboard: false,
      show: true,
      backdrop: 'static'
  })

  $('#collectionUserInfo').on('hidden.bs.modal', function () {
      var groups = $("#groups").val()||'';
      connect=initSignalr({
          delay: 0,
          url:`${notifyUrl}notify-hub?userId=${vm.userInfo.userName}&group=${groups}`,
          loggingLevel: signalR.LogLevel.Error,
          onNotify: dealNotify,
          onLine: function (data) {
              if (data.IsFirst) {
                  getOnlineUsers();
              }
              getOnlineGroups();
              vm.logs.push(`新鏈接上線:${JSON.stringify(data)}`);
          },
          offLine: function (data) {
              if (data.IsLast) {
                  getOnlineUsers();
              }
              getOnlineGroups();
              vm.logs.push(`鏈接下線:${JSON.stringify(data)}`);
          },
          onStarted: function () {
              getOnlineUsers();
              getOnlineGroups();
              vm.$set(vm.userInfo, 'connectionId', connect.connectionId);
              vm.$set(vm.userInfo, 'groups', groups);
              vm.logs.push('鏈接成功');
          }
      });
  })
  }

onNotify方法,若是仔細的話會看到裏面的onNotify方法,全部的推送最終都會調用到該方法來進行分發。查看代碼
offLine,當有客戶端下線的時候會觸發,data裏面包含有用戶Id、鏈接Id、是否該用戶的最後一個鏈接,可根據須要使用查看代碼
onLine,當用戶鏈接的時候會觸發,data裏面包含有用戶Id、鏈接Id、是否該用戶的第一個鏈接(用於用戶上線後的邏輯處理),可根據須要使用 查看代碼
onStarted,當成功鏈接後觸發,可用於作一些鏈接後的業務邏輯處理,可根據須要使用 查看代碼後端

獲取當前用戶信息、在線列表

在用戶鏈接成功後,獲取當前在線用戶、用戶組、當前用戶信息,並設置到vue的data中 查看代碼api

模擬一個任務分配

在項目中心中,點擊"模擬推送待辦"按鈕,將會向當前用戶所在組中推送一條代碼消息,能夠登陸不一樣帳號、開多個tab頁體驗
點擊事件代碼位置 查看代碼瀏覽器

assignTaskToUser: function () {
    var that = this;
    $.ajax({
        type: 'POST',
        url: '/api/ServerProxy/AssignTaskToUser',
        data: {
            groups:that.userInfo.groups
        }
    })
},

對應的推送解析代碼

首先當有推送過來的時候,會首先進到onNotify方法,而後根據不一樣類型在分配到不一樣的js方法中
查看代碼
效果圖
20190927212304.png

模擬發送消息

消息發送,能夠選定組、人進行消息發送
發送端代碼
解析端

登陸互斥

登陸互斥是指,當一個帳號在A電腦登陸,而後再在B電腦登陸,最後的登陸會排斥掉開始的登陸,即,將A上的擠下線
首先用谷歌瀏覽器登陸,輸入用戶名:xiexingen,而後鏈接
接着使用360急速瀏覽器登陸,輸入用戶名:xiexingen 這個時候會發現谷歌瀏覽器中的登陸已經退出,如圖
20190927213637.png

必要條件: 不一樣瀏覽器、同一用戶,好比:同一個瀏覽器,不一樣tab就不算(能共用cookie)

文件下載(指定鏈接推送)

文件下載的場景,用戶在操做頁面上選擇了上千個文件,而後點擊打包下載,這個時候可能須要好久時間才反應回來,那麼這段時間若是讓用戶一直等待顯然不妥,因此,當用戶點擊打包下載的時候,後端啓用一個後臺線程去打包、壓縮,而後當即返回;用戶能夠繼續操做,當服務器端打包好後推送給用戶端,用戶點擊下載便可。
此處分兩種狀況

  1. 單鏈接推送

用戶開了多個tab頁,在其中一個上下載文件,若是後端推送的時候,直接給該用戶推,顯然不妥;正確的作法一個是隻給操做的那個tab頁推,這就須要,調用服務器端業務api的時候,須要把當前tab頁對應的鏈接id發送到服務器端,服務器端處理完業務後,調用推送服務器,告訴推送服務器只推我給你的這個鏈接的客戶端,這樣就能指定鏈接推送。

  1. 單用戶排除某個鏈接的其餘鏈接推送

這種狀況比較少見,告訴推送服務器,給這個用戶,除了某個鏈接外的其餘全部鏈接推送

模擬操做
點擊第一個圖中的"打包下載文件" 按鈕,當前頁面會受到文件下載的推送
在點擊圖二中的"推送當前用戶其餘頁面更新操做"按鈕,會發現出了當前tab頁外,其餘tab也都收到了推送消息,以下圖
20190927214530.png

至此,signalr相關文章算是到此結束了,下一篇談談我的的一點心得以及裏面存着的一些問題。

快速導航

標題 內容
索引 .net core 3.0 Signalr - 實現一個業務推送系統
上一篇 .net core 3.0 Signalr - 07 業務實現-服務端 自定義管理組、用戶、鏈接
下一篇 .net core 3.0 Signalr - 09 待改進&交流
源碼地址 源碼
官方文檔 官方文檔

二維碼

相關文章
相關標籤/搜索