在Volo.Abp微服务中使用SignalR

假设需要通过SignalR发送消息通知,并在前端接收消息通知的功能

创建SignalR服务

在项目中引用

abp add-package Volo.Abp.AspNetCore.SignalR

在Module文件中添加对模块依赖

[DependsOn(
    ...
    typeof(AbpAspNetCoreSignalRModule)
    )]
public class IdentityApplicationModule : AbpModule

创建接口INotificationHub

public interface INotificationHub
{
    // 发送消息
    Task ReceiveTextMessageAsync(SendNotificationDto input);
}

也可以不创建接口,AbpHub类,定义了泛型和非泛型的类型。

创建NotificationHub类,继承AbpHub。
可以直接继承Microsoft.AspNetCore.SignalR.Hub,但是这样就不能使用已注入的属性,如 CurrentUser

/// <summary>
/// SignalR消息Hub
/// </summary>
[HubRoute("signalr/Identity/notification")]
[Authorize]
[DisableAuditing]
public class NotificationHub : AbpHub<INotificationHub>
{

}

发送SignalR消息

在需要调用的地方注入IHubContext,并初始化

private readonly IHubContext<NotificationHub, INotificationHub> _hubContext;
public NotificationAppService(IHubContext<NotificationHub, INotificationHub> hubContext) 
{
    _hubContext = hubContext;
}

使用下面的方式发送给指定用户或者所有用户

public async Task SendMessageToUsersAsync(List<string> userIds, SendNotificationDto sendNotificationDto)
{
    await _hubContext.Clients
        .Users(userIds.AsReadOnly().ToList())
        .ReceiveTextMessageAsync(sendNotificationDto);
}


public async Task SendMessageToAllAsync(SendNotificationDto sendNotificationDto)
{
    await _hubContext.Clients.All.ReceiveBroadCastMessageAsync(sendNotificationDto);
}

配置Ocelet网关

为/signalr/identity/路由创建转发规则

当SignalR开始连接时,首先发送协商协议请求,协商协议返回availableTransports告诉客户端支持哪些协议,以及connetcionId和connectionToken,这两个值会在后续的连接中使用。

在这里插入图片描述

在当前路由配置下,请求地址是:/signalr/identity/negotiate,此http请求会通过网关转发到IdentityServer。

在Gateway项目的appsettings.json中配置网关转发规则,如下:

"Routes": [
    {
      "DownstreamPathTemplate": "/signalr/identity/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44368
        }
      ],
      "UpstreamPathTemplate": "/signalr/identity/{everything}",
      "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
    },
    ...

除此之外还要配置ws协议的转发规则,SignalR首先尝试建立WebSocket连接,WebSocket是 SignalR的最佳传输方式,配置如下:

  {
    "DownstreamPathTemplate": "/signalr/identity/{everything}",
    "DownstreamScheme": "ws",
    "Priority": 1,
    "DownstreamHostAndPorts": [
      {
        "Host": "localhost",
        "Port": 44368
      }
    ],
    "UpstreamPathTemplate": "/signalr/identity/{everything}",
    "UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
  },

创建SignalR客户端

客户端安装取决于你的UI框架/客户端类型。若使用Asp.NetCore MVC或Razor,请参考abp官方文档
这里补充其他UI框架的使用方法。在webpackage项目中添加对SignalR的依赖

yarn add @microsoft/signalr

创建一个hubConnection
在main.js中添加如下代码

const hubConnection: signalR.HubConnection = new signalR.HubConnectionBuilder()
  .withUrl(baseURL + requestUrl, {
    headers: header,
    accessTokenFactory: () => getAccessToken(),
    transport: signalR.HttpTransportType.WebSockets,
    logMessageContent: true,
    logger: signalR.LogLevel.Information,
  })
  .withAutomaticReconnect()
  .withHubProtocol(new signalR.JsonHubProtocol())
  .build();

accessTokenFactory回调用于获取access_token的,会在每次请求时调用以保证获取最新的access_token。

连接服务

在需要使用的地方调用hubConnection方法

hubConnection.start() //开始连接
hubConnection.stop()  //停止连接

订阅消息

hubConnection.on("ReceiveTextMessage", (newMsg) => {
  console.info("new msg recived!", newMsg)
});

身份验证

WebSockets不支持自定义Header,所以不能使用Authorization,需要使用access_token参数传递令牌

客户端

在客户端中配置getAccessToken,如下:

const getAccessToken: Function = (): string => {
  var token = UserModule.token !== undefined ? UserModule.token : ""; 
  return token;
}

UserModule.token是当前登录用户的token,需要在登录成功后保存到UserModule中。

服务端

在服务端中,若已经使用了IdentityServer,则需要在Startup中配置IdentityServerAuthentication,配置如下:

context.Services.AddAuthentication("Bearer")
    .AddIdentityServerAuthentication(options =>
    {
        options.Authority = configuration["AuthServer:Authority"];
        options.ApiName = configuration["AuthServer:ApiName"];
        options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
        options.TokenRetriever = (request) =>
        {
            var path = request.Path;
            if (path.StartsWithSegments("/signalr"))
            {
                var accessToken = request.Query["access_token"].FirstOrDefault();

                if (!accessToken.IsNullOrWhiteSpace())
                {
                    return accessToken;
                }
            }
            return TokenRetrieval.FromAuthorizationHeader().Invoke(request);

        };                  
    });
    

如果你适用IISExpress运行项目,注意此时SignalR的url参数可能过长而报告404.15 - Query String Too Long,IIS默认限制是2048,需要在C:\Windows\System32\inetsrv\config\applicationHost.config中配置maxQueryString规则,如下:

<configuration>
   <system.webServer>
      <security>
         <requestFiltering>
             <requestLimits maxQueryString="4096" />
         </requestFiltering>
      </security>
   </system.webServer>
</configuration>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/56920.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spring】学习Spring需要掌握的核心设计思想

目录 一、Spring是什么 二、什么是IoC容器 1、什么是容器 2、什么是IoC 3、Spring IoC 4、DI&#xff08;依赖注入&#xff09; 4.1、IoC和DI的区别 5、 DL&#xff08;依赖查找&#xff09; 一、Spring是什么 我们通常所说的Spring指的是Spring Framework&#xff08;…

Vue3徽标数(Badge)

APIs 参数说明类型默认值必传color自定义小圆点的颜色string‘’falsecount展示的数字&#xff0c;大于 overflowCount 时显示为 overflowCount&#xff0c;为 0 时隐藏number | slot0falseoverflowCount展示封顶的数字值number99falseshowZero当数值为 0 时&#xff0c;是否展…

Django实现音乐网站 ⑵

使用Python Django框架制作一个音乐网站&#xff0c;在系列文章1的基础上继续开发&#xff0c;本篇主要是后台歌手表模块开发。 目录 表结构设计 歌手表&#xff08;singer&#xff09;结构 创建表模型 设置图片上传路径 创建上传文件目录 生成表迁移 执行创建表 后台管…

PUBG(最短路BFS)

题目&#xff1a;https://ac.nowcoder.com/acm/contest/62106/E 最近&#xff0c;喜爱ACM的PBY同学沉迷吃鸡&#xff0c;无法自拔&#xff0c;于是又来到了熟悉的ERANGEL。经过一番搜寻&#xff0c;PBY同学准备动身前往安全区&#xff0c;但是&#xff0c;地图中埋伏了许多LYB&…

2023年第四届“华数杯”数学建模思路 - 案例:FPTree-频繁模式树算法

## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c;他与Apriori算法一样也是用来挖掘频繁项集的&#xff0c…

阿里云OSS的开通+配置及其使用

云存储解决方案-阿里云OSS 文章目录 云存储解决方案-阿里云OSS1. 阿里云OSS简介2. OSS开通&#xff08;1&#xff09;打开https://www.aliyun.com/ &#xff0c;申请阿里云账号并完成实名认证。&#xff08;2&#xff09;充值 (可以不用做)&#xff08;3&#xff09;开通OSS&am…

STM32F1基于标准库ST7735 1.8‘‘LCD显示DHT11数据

STM32基于标准库ST7735 1.8‘’LCD显示DHT11数据 &#x1f4cd;HAL库驱动可以参考&#xff1a;《STM32基于HAL工程读取DHT11数据》&#x1f33c;显示效果&#xff1a; &#x1f33b;ST7735 128x160 1.8’LCD屏幕 &#x1f4cc;屏幕资料和相关驱动可以参考《1.8寸TFT LCD128…

《golang设计模式》第一部分·创建型模式-04-抽象工厂模式(Abstract Factory)

文章目录 1. 概述1.1 角色1.2 类图 2. 代码示例2.1 设计2.2 代码2.3 类图 1. 概述 1.1 角色 AbstractFactory&#xff08;抽象工厂&#xff09;&#xff1a;它声明了一组用于创建产品的方法&#xff0c;每一个方法对应一种产品。ConcreteFactory&#xff08;具体工厂&#xf…

ArmSoM-W3之RK3588安装Qt+opencv+采集摄像头画面

1. 简介 场景&#xff1a;在RK3588上做qt开发工作 RK3588安装Qtopencv采集摄像头画面 2. 环境介绍 这里使用了OpenCV所带的库函数捕获摄像头的视频图像。 硬件环境&#xff1a; ArmSoM-RK3588开发板、&#xff08;MIPI-DSI&#xff09;摄像头 软件版本&#xff1a; OS&…

[C++]

C 一.C基础入门1.HelloWorld2.注释3.变量4.常量5.关键字6.命名规则 二.数据类型1.整形2.sizeof关键字3.浮点型4.字符型5.转义字符6.字符串型7.布尔类型8.数据的输入 三.运算符1.算数运算符2.赋值运算符3.比较运算符4.逻辑运算符 一.C基础入门 1.HelloWorld 首先到官网下载并安…

贯穿设计模式--开闭原则

&#x1f335;概述 该原则主要说明的是扩展开放&#xff0c;对修改关闭&#xff0c;即尽量通过扩展软件实体类等来解决需求变化&#xff0c;而不是通过修改已有的代码来完成变化&#xff1b;实现开闭原则的核心思想就是面向抽象编程&#xff0c;强调的是用抽象构建框架&#x…

Windows驱动开发必备工具

Windows驱动开发必备工具 设备树文软件 可以查看设备信息 数字签名工具安装包 开发用的数字签名证书密钥 断点命中工具包&#xff08;双机调试必备&#xff09; 二进制文件解析工具 日志查看工具&#xff08;必备&#xff09; IRP查看工具 C驱动开发相关书籍 有需要工具、书籍…

怎么学习CSS相关技术知识? - 易智编译EaseEditing

学习CSS技术是前端开发中的重要一环&#xff0c;它用于控制网页的样式和布局&#xff0c;使网页更加美观和易于使用。以下是学习CSS技术的几个方面&#xff1a; 基本语法和选择器&#xff1a; 了解CSS的基本语法&#xff0c;学习如何使用选择器来选择HTML元素并应用样式。 样…

vim、awk、tail、grep的使用

vim命令 $定位到光标所在行的行末^定位到光标所在行的行首gg定位到文件的首行G定位到文件的末行dd删除光标所在行ndd删除n行&#xff08;从光标所在行开始&#xff09;D删除光标所在行&#xff0c;使之变为空白行x删除光标所在位置字符nx删除n个字符&#xff0c;从光标开始向后…

使用Flutter的image_picker插件实现设备的相册的访问和拍照

文章目录 需求描述Flutter插件image_picker的介绍使用步骤1、添加依赖2、导入 例子完整的代码效果 总结 需求描述 在应用开发时&#xff0c;我们有很多场景要使用到更换图片的功能&#xff0c;即将原本的图像替换设置成其他的图像&#xff0c;从设备的相册或相机中选择图片或拍…

CAD .NET 15.0 企业版 Crack

CAD .NET 15.0 企业版 企业版 企业版 企业版 企业版 Updated: June 14, 2023 | Version 15.0 NEW CAD .NET is a library for developing solutions in .NET environment. It supports AutoCAD DWG/ DXF, PLT and other CAD formats. The library can be used in a wide rang…

visual studio 生成dll文件以及修改输出dll文件名称操作

目录 visual studio 生成dll文件以及修改dll文件名称一、准备测试代码二、设置导出dll属性三、生成dll文件 .lib .dll .pdb 的简单介绍dll文件使用方式lib文件使用方式1、动态链接 &#xff08;原理&#xff09;2、静态链接&#xff1a; visual studio 生成dll文件以及修改dll文…

flex 弹性布局

Flex 布局的使用 任何一个容器都可以指定为 Flex 布局。 .box{ display: flex; //flex作为display的一个属性使用 } 行内元素也可以使用 Flex 布局。 .box{ display: inline-flex; } 注意&#xff1a;设为 Flex 布局以后&#xff0c;子元素的float、clear和vertical-align…

MySQL做分布式锁

分布式锁mysql实现方式 方式1&#xff1a;唯一索引 创建锁表&#xff0c;内部存在字段表示资源名及资源描述&#xff0c;同一资源名使用数据库唯一性限制。多个进程同时往数据库锁表中写入对某个资源的占有记录&#xff0c;当某个进程成功写入时则表示其获取锁成功其他进程由于…

备战秋招 | 笔试强化22

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、在有序双向链表中定位删除一个元素的平均时间复杂度为 A. O(1) B. O(N) C. O(logN) D. O(N*logN) 2、在一个以 h 为头指针的单循环链表中&#xff0c;p 指针指向链尾结点的条件是( ) A. p->ne…