重构代码:移除WebSockets相关逻辑,使用SignalR
This commit is contained in:
parent
b528810516
commit
26581b6b3b
|
@ -1,5 +1,6 @@
|
||||||
using Bootstrap.DataAccess;
|
using Bootstrap.DataAccess;
|
||||||
using Bootstrap.Security;
|
using Bootstrap.Security;
|
||||||
|
using Longbow.Web.SignalR;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -26,10 +27,10 @@ namespace Bootstrap.Admin.Controllers.Api
|
||||||
/// <param name="user"></param>
|
/// <param name="user"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public bool Post([FromBody] User user)
|
public bool Post([FromServices]ISignalRHubContext<SignalRHub> hub, [FromBody]User user)
|
||||||
{
|
{
|
||||||
var ret = UserHelper.SaveUser(user);
|
var ret = UserHelper.SaveUser(user);
|
||||||
if (ret) NotificationHelper.PushMessage(new MessageBody() { Category = "Users", Message = string.Format("{0}-{1}", user.UserName, user.Description) });
|
if (ret) hub.SendAll(new MessageBody() { Category = "Users", Message = string.Format("{0}-{1}", user.UserName, user.Description) });
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
using Bootstrap.DataAccess;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Bootstrap.Admin.Controllers.Api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
public class WSController : Controller
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpPost]
|
|
||||||
public IEnumerable<MessageBody> Post()
|
|
||||||
{
|
|
||||||
return NotificationHelper.RetrieveMessages();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,7 +7,7 @@ using Longbow.Configuration;
|
||||||
using Longbow.Data;
|
using Longbow.Data;
|
||||||
using Longbow.Logging;
|
using Longbow.Logging;
|
||||||
using Longbow.Web;
|
using Longbow.Web;
|
||||||
using Longbow.Web.WebSockets;
|
using Longbow.Web.SignalR;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
@ -50,6 +50,7 @@ namespace Bootstrap.Admin
|
||||||
.SetApplicationName(Configuration["ApplicationName"])
|
.SetApplicationName(Configuration["ApplicationName"])
|
||||||
.PersistKeysToFileSystem(new DirectoryInfo(Configuration["KeyPath"]));
|
.PersistKeysToFileSystem(new DirectoryInfo(Configuration["KeyPath"]));
|
||||||
if (Configuration["DisableAutomaticKeyGeneration"] == "True") dataProtectionBuilder.DisableAutomaticKeyGeneration();
|
if (Configuration["DisableAutomaticKeyGeneration"] == "True") dataProtectionBuilder.DisableAutomaticKeyGeneration();
|
||||||
|
services.AddSignalRManager();
|
||||||
services.AddMvc(options =>
|
services.AddMvc(options =>
|
||||||
{
|
{
|
||||||
options.Filters.Add<BootstrapAdminAuthorizeFilter>();
|
options.Filters.Add<BootstrapAdminAuthorizeFilter>();
|
||||||
|
@ -81,8 +82,8 @@ namespace Bootstrap.Admin
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseBootstrapAdminAuthorization();
|
app.UseBootstrapAdminAuthorization();
|
||||||
app.UseWebSocketHandler(options => options.UseAuthentication = true, WSHelper.WebSocketMessageHandler);
|
|
||||||
app.UseCacheManagerCorsHandler();
|
app.UseCacheManagerCorsHandler();
|
||||||
|
app.UseSignalR(routes => { routes.MapHub("/NotiHub"); });
|
||||||
app.UseMvc(routes =>
|
app.UseMvc(routes =>
|
||||||
{
|
{
|
||||||
routes.MapRoute(
|
routes.MapRoute(
|
||||||
|
|
|
@ -18,11 +18,13 @@
|
||||||
<environment include="Development">
|
<environment include="Development">
|
||||||
<script src="~/js/sweetalert.js"></script>
|
<script src="~/js/sweetalert.js"></script>
|
||||||
<script src="~/js/jquery.mCustomScrollbar.js"></script>
|
<script src="~/js/jquery.mCustomScrollbar.js"></script>
|
||||||
|
<script src="~/js/signalr.js"></script>
|
||||||
<script src="~/js/toastr.js"></script>
|
<script src="~/js/toastr.js"></script>
|
||||||
</environment>
|
</environment>
|
||||||
<environment exclude="Development">
|
<environment exclude="Development">
|
||||||
<script src="~/js/sweetalert.min.js"></script>
|
<script src="~/js/sweetalert.min.js"></script>
|
||||||
<script src="~/js/jquery.mCustomScrollbar.concat.min.js"></script>
|
<script src="~/js/jquery.mCustomScrollbar.concat.min.js"></script>
|
||||||
|
<script src="~/js/signalr.min.js"></script>
|
||||||
<script src="~/js/toastr.min.js"></script>
|
<script src="~/js/toastr.min.js"></script>
|
||||||
</environment>
|
</environment>
|
||||||
<script src="~/js/jquery.dcjqaccordion.2.7.js"></script>
|
<script src="~/js/jquery.dcjqaccordion.2.7.js"></script>
|
||||||
|
|
|
@ -216,25 +216,23 @@ $(function () {
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
|
|
||||||
// load widget data
|
// load widget data
|
||||||
$('.header .nav').reloadWidget().socketHandler({
|
$('.header .nav').reloadWidget().notifi({
|
||||||
onmessage: function (e) {
|
url: 'NotiHub',
|
||||||
var result = JSON.parse(e.data);
|
callback: function (result) {
|
||||||
for (index in result) {
|
var cate = result.Category;
|
||||||
var cate = result[index].Category;
|
var msg = result.Message;
|
||||||
var msg = result[index].Message;
|
switch (cate) {
|
||||||
switch (cate) {
|
case "DB":
|
||||||
case "DB":
|
toastr.error(msg, "数据库操作发生异常");
|
||||||
toastr.error(msg, "数据库操作发生异常");
|
break;
|
||||||
break;
|
case "Users":
|
||||||
case "Users":
|
toastr.success(msg, "新用户注册");
|
||||||
toastr.success(msg, "新用户注册");
|
break;
|
||||||
break;
|
case "App":
|
||||||
case "App":
|
toastr.warning(msg, "应用程序发生异常");
|
||||||
toastr.warning(msg, "应用程序发生异常");
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (result.length > 0) this.reloadWidget();
|
if (result) this.reloadWidget();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -286,74 +286,18 @@
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
msgHandler: function (options) {
|
notifi: function (options) {
|
||||||
var settings = {
|
var op = $.extend({ url: '', method: 'rev', callback: false }, options);
|
||||||
url: 'api/WS',
|
var connection = new signalR.HubConnectionBuilder().withUrl($.formatUrl(op.url)).build();
|
||||||
interval: 10000,
|
var that = this;
|
||||||
sendMessage: '',
|
connection.on(op.method, function () {
|
||||||
timerHandler: null,
|
if ($.isFunction(op.callback)) {
|
||||||
onopen: function (e) { },
|
op.callback.apply(that, arguments);
|
||||||
onmessage: function (e) { },
|
|
||||||
onclose: function (e) { },
|
|
||||||
errorHandler: function (e) { if (toastr && $.isFunction(toastr.error)) toastr.error("连接服务器失败!", "系统错误"); },
|
|
||||||
loop: function () {
|
|
||||||
var that = this;
|
|
||||||
var uri = window.location.protocol + "//" + window.location.host + $.formatUrl(settings.url);
|
|
||||||
$.bc({
|
|
||||||
url: uri,
|
|
||||||
id: this.sendMessage,
|
|
||||||
method: "post",
|
|
||||||
callback: function (result) {
|
|
||||||
if (!result) {
|
|
||||||
that.errorHandler.call(that.target);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
that.onmessage.call(that.target, { data: JSON.stringify(result) });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.timerHandler !== null) clearTimeout(this.timerHandler);
|
|
||||||
this.timerHandler = setTimeout(function () { that.loop(); }, that.interval);
|
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
$.extend(settings, options, { target: this });
|
connection.start().catch(function (err) {
|
||||||
settings.loop();
|
return console.error(err.toString());
|
||||||
return this;
|
});
|
||||||
},
|
|
||||||
socketHandler: function (options) {
|
|
||||||
// WebSocket消息处理方法
|
|
||||||
var settings = {
|
|
||||||
url: 'WS',
|
|
||||||
interval: 30000,
|
|
||||||
sendMessage: 'keepalive',
|
|
||||||
timerHandler: null,
|
|
||||||
onopen: function (e) { },
|
|
||||||
onerror: function (e) { },
|
|
||||||
errorHandler: function (e) { if (window.toastr && $.isFunction(window.toastr.error)) toastr.error("连接服务器失败!", "系统错误"); },
|
|
||||||
onmessage: function (e) { },
|
|
||||||
onclose: function (e) { },
|
|
||||||
loop: function (socket) {
|
|
||||||
var that = this;
|
|
||||||
if (socket.readyState === 1) {
|
|
||||||
socket.send(this.sendMessage);
|
|
||||||
if (this.timerHandler !== null) clearTimeout(this.timerHandler);
|
|
||||||
this.timerHandler = setTimeout(function () { that.loop(socket); }, that.interval);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.errorHandler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$.extend(settings, options, { target: this });
|
|
||||||
var uri = "ws://" + window.location.host + $.formatUrl(settings.url);
|
|
||||||
var socket = new WebSocket(uri);
|
|
||||||
socket.onopen = function (e) { settings.onopen.call(settings.target, e); settings.loop(socket); };
|
|
||||||
socket.onerror = function (e) {
|
|
||||||
settings.onerror.call(settings.target, e);
|
|
||||||
settings.target.msgHandler(options);
|
|
||||||
};
|
|
||||||
socket.onmessage = function (e) { settings.onmessage.call(settings.target, e); };
|
|
||||||
socket.onclose = function (e) { settings.onclose.call(settings.target, e); };
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,14 +1,12 @@
|
||||||
using Longbow.Cache;
|
using Longbow.Cache;
|
||||||
using Longbow.Configuration;
|
using Longbow.Configuration;
|
||||||
using Longbow.Data;
|
using Longbow.Data;
|
||||||
using Longbow.Web.WebSockets;
|
using Longbow.Web.SignalR;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Bootstrap.DataAccess
|
namespace Bootstrap.DataAccess
|
||||||
{
|
{
|
||||||
|
@ -42,16 +40,18 @@ namespace Bootstrap.DataAccess
|
||||||
cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@StackTrace", DBAccessFactory.ToDBValue(ex.StackTrace)));
|
cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@StackTrace", DBAccessFactory.ToDBValue(ex.StackTrace)));
|
||||||
DBAccessManager.SqlDBAccess.ExecuteNonQuery(cmd);
|
DBAccessManager.SqlDBAccess.ExecuteNonQuery(cmd);
|
||||||
CacheManager.Clear(RetrieveExceptionsDataKey);
|
CacheManager.Clear(RetrieveExceptionsDataKey);
|
||||||
|
ClearExceptions();
|
||||||
|
|
||||||
var category = "App";
|
var category = "App";
|
||||||
if (ex.GetType().IsSubclassOf(typeof(DbException))) category = "DB";
|
if (ex.GetType().IsSubclassOf(typeof(DbException))) category = "DB";
|
||||||
WebSocketServerManager.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new MessageBody[] { new MessageBody() { Category = category, Message = ex.Message } }))));
|
var message = new MessageBody() { Category = category, Message = ex.Message };
|
||||||
ClearExceptionsAsync();
|
SignalRManager.Get().SendAll(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void ClearExceptionsAsync()
|
private static void ClearExceptions()
|
||||||
{
|
{
|
||||||
System.Threading.Tasks.Task.Run(() =>
|
System.Threading.Tasks.Task.Run(() =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace Bootstrap.DataAccess
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class MessageBody
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string Message { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string Category { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format("{0}-{1}", Category, Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,70 +0,0 @@
|
||||||
using Longbow.Cache;
|
|
||||||
using Longbow.Web.WebSockets;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Bootstrap.DataAccess
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class NotificationHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
private const string PullNotificationsIntervalDataKey = "NotificationHelper-PullNotificationsInterval";
|
|
||||||
private static readonly List<MessageBody> MessagePool = new List<MessageBody>();
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static void PushMessage(MessageBody message)
|
|
||||||
{
|
|
||||||
MessagePool.Add(message);
|
|
||||||
CacheManager.Clear(PullNotificationsIntervalDataKey);
|
|
||||||
|
|
||||||
// websocket message push
|
|
||||||
WebSocketServerManager.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new MessageBody[] { message }))));
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static IEnumerable<MessageBody> RetrieveMessages()
|
|
||||||
{
|
|
||||||
return CacheManager.GetOrAdd(PullNotificationsIntervalDataKey, key =>
|
|
||||||
{
|
|
||||||
var msgs = new MessageBody[MessagePool.Count];
|
|
||||||
MessagePool.CopyTo(msgs, 0);
|
|
||||||
MessagePool.Clear();
|
|
||||||
return new List<MessageBody>(msgs);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class MessageBody
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Message { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Category { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return string.Format("{0}-{1}", Category, Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
namespace Bootstrap.DataAccess
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class WSHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="socket"></param>
|
|
||||||
/// <param name="data"></param>
|
|
||||||
public static byte[] WebSocketMessageHandler(byte[] data)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue