RuoYi-Cloud-Plus集成 WebSocket

这篇具有很好参考价值的文章主要介绍了RuoYi-Cloud-Plus集成 WebSocket。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

学习地址:https://blog.csdn.net/qq_43898141/article/details/123744468

  1. 添加websocket 依赖
 <!--添加websockert依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId><exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </exclusion>
    </exclusions>
  1. 添加配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
    public class WebSocketConfig {

        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    }

  1. webSocket 代码
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.ruoyi.common.core.config.systemConfig;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.common.redis.service.RedisService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


@ServerEndpoint(value = "/websocket/{userName}")
@Component
public class WebSocketService implements Serializable {

    //concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
    @JsonBackReference
    private static Map<String, WebSocketService> webSocketMap = new ConcurrentHashMap<>();

    /**
     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    private Session session;
    /**
     * 接收userName
     */
    private String userName = "";

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userName") String userName) {
        this.session = session;
        this.userName = userName;
        webSocketMap.put(userName, this);
        System.err.println("----------------------------------------------------------------------------");
        System.err.println("用户连接:" + userName + ":" + userName + ",当前在线人数为:" + webSocketMap.size());
        sendMessage("来自后台的反馈:连接成功");
        webSocketMap.forEach((k, v) -> System.err.println(k));
    }


    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("userName") String userName) {
        if (webSocketMap.containsKey(userName)) {
            webSocketMap.remove(userName);
        }
        System.err.println("----------------------------------------------------------------------------");
        System.err.println(userName + "用户退出,当前在线人数为:" + webSocketMap.size());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.err.println("收到用户消息:" + userName + ",报文:" + message);
        //可以群发消息
        //消息保存到数据库、redis
        if (message != null) System.err.println("");
    }

    /**
     * 连接失败调用方法
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.err.println("用户错误:" + this.userName + ",原因:" + error.getMessage());
        error.printStackTrace();
    }


    /**
     * 连接服务器成功后主动推送
     */
    public void sendMessage(String message) {
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    /**
     * 向指定客户端发送消息
     * <p>
     * // * @param userName
     * //* @param message
     */
    public static void sendMessage(String userName, String message) {
        try {
            WebSocketService webSocketService = webSocketMap.get(userName);
            if (webSocketService != null) {
                webSocketService.getSession().getBasicRemote().sendText(message);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }


  //下面方法根据自己情况 删 留
    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public static Map<String, WebSocketService> getWebSocketMap() {
        return webSocketMap;
    }

    public static void setWebSocketMap(Map<String, WebSocketService> webSocketMap) {
        WebSocketService.webSocketMap = webSocketMap;
    }

    public static void put(String key, WebSocketService data) {
        webSocketMap.put(key, data);
    }

    public static WebSocketService get(String key) {
        return webSocketMap.get(key);
    }

    public static void del(String key) {
        webSocketMap.remove(key);
    }

  1. 网管配置服务转发
# websocket模块
        #服务名称
- id: ruoyi-chat-websocket
  #转发的服务
  uri: lb:ws://ruoyi-chat
  #转发设置
  predicates:
    - Path=/websocket/**
  #请求地址后一位,如:/socket/xxx/xx  去掉socket = /xxx/xx
  filters:
    - StripPrefix=1

网关配置

  1. 重要: 如果你的webSocket 没有Token 也没有任何认证的话 需要开放白名单。

配置

 # 不校验白名单
  ignore:
    whites:
      - /code
      - /auth/logout
      - /auth/login
      - /auth/smsLogin
      - /auth/xcxLogin
      - /auth/mobileLogin
      - /websocket/**
  1. **开始测试 **http://www.jsons.cn/websocket/

image.png

  1. 如果出现连接成功 立马断开的问题 排查思路如下
    1. 排查网关里面的转发url 是否使用的ws=> lb:ws://ruoyi-chat
    2. 是否开启了白名单

如果以上都可以了 还是不行,那就是因为他的子模块默认也是需要Token 权限的 我在解决了两天的情况下发现 需要加上以下配置

  1. 在 SecurityConfiguration implements WebMvcConfigurer 文件下面增加 放过
/**
* 校验是否从网关转发
*/
@Bean
    public SaServletFilter getSaServletFilter() {
    return new SaServletFilter()
        .addInclude("/**")
        .addExclude("/actuator/**")
        .addExclude("/socket/**")
        .setAuth(obj -> SaIdUtil.checkCurrentRequestToken())
        .setError(e -> SaResult.error("认证失败,无法访问系统资源").setCode(HttpStatus.UNAUTHORIZED));
}

出现的错误提示

WebSocketClientHandshakeException Create breakpoint : Invalid handshake response getStatus: 200 OK

An exception has been observed post termination, use DEBUG level to see the full stack:io.netty . handler . codec . http . websocketx . webSocketClientHandshakeExcept ion: Connection prematurely closed BEFORE opening handshake is complete.

结论:

在子模块中也是需要鉴权的Token 的如果只在网管放开白名单 在子模块也是不行的 所以直接在这个地方加上文章来源地址https://www.toymoban.com/news/detail-425282.html

import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.id.SaIdUtil;
import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
import cn.dev33.satoken.util.SaResult;
import com.yawei.common.core.constant.HttpStatus;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 权限安全配置
 *
 * @author Suiquantong
 */
@AutoConfiguration
public class SecurityConfiguration implements WebMvcConfigurer {

    /**
     * 注册sa-token的拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注解拦截器
        registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
    }

    /**
     * 校验是否从网关转发
     */
    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()
            .addInclude("/**")
            .addExclude("/actuator/**")
            .addExclude("/socket/**")
            .setAuth(obj -> SaIdUtil.checkCurrentRequestToken())
            .setError(e -> SaResult.error("认证失败,无法访问系统资源").setCode(HttpStatus.UNAUTHORIZED));
    }

}

到了这里,关于RuoYi-Cloud-Plus集成 WebSocket的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 重写RuoYi-Cloud所有功能 整合 SpringCloudAlibaba Dubbo Mybatis-Plus MQ OSS ES Xxl-Job Docker 全方位升级 定期同步

    转载于:https://blog.csdn.net/weixin_40461281/article/details/122837923 RuoYi-Cloud-Plus  微服务通用权限管理系统  重写 RuoYi-Cloud 全方位升级(不兼容原框架) 系统演示: 传送门 分布式集群版本(功能一致) 功能介绍 使用技术 文档地址 特性注意事项 微服务权限管理系统 RuoYi-Cloud-Plus RuoYi-Clo

    2024年02月08日
    浏览(35)
  • ruoyi-cloud部署

    默认你已经安装mysql,nacos,seata,sentinel等(没有的可以先找教程安装) 1、下载源码:git clone https://gitee.com/zhangmrit/ruoyi-cloud 2、项目依赖导入,选择自己的maven环境等,创建三个库ry-cloud、ry-config、ry-seata执行下面三个sql,把quartz放到ry-cloud 3、nacos配置,生成配置列表(配置该

    2024年02月11日
    浏览(41)
  • RuoYi-Flowable-Plus搭建(若依)

    项目简介 业务功能 拉取代码 建库建表 修改配置 后端启动 前端启动 项目访问(http://localhost:81) ​​ ​ 测试SQL

    2024年02月16日
    浏览(27)
  • RuoYi-Vue-Plus搭建(若依)

     项目简介 业务功能 拉取代码 建库建表 修改配置 后端启动 前端启动 项目访问(http://localhost:81) ​​ ​ ​ ​

    2024年02月11日
    浏览(29)
  • RuoYi -Cloud开源框架-跨域配置

    🦆博主介绍:小黄鸭技术 🌈擅长领域:Java、实用工具、运维 👀 系列专栏:📢开发工具 Java之路 八股文之路 📧如果文章写作时有错误的地方,请各位大佬指正,一起进步!!! 🧡欢迎大家点赞➕收藏⭐➕评论💬支持博主🤞   目录  什么是跨域 RoYi-Cloud如何解决跨域

    2024年02月03日
    浏览(32)
  • RuoYi-Cloud微服务开发实战

    目录 第一章 开发环境搭建 前言 一、RuoYi-Cloud是什么? 二、环境部署 1.安装JDK 2.安装docker 3.下载mysql镜像 4.下载redis镜像 5.下载nacos-server 镜像 6.安装node.js 三、项目启动 开发设备:         MacBook Pro(14英寸,2021年)         系统版本:macOS Monterey         芯片:

    2024年02月16日
    浏览(42)
  • ruoyi-cloud—若依微服务打包部署

    1. 前端端口修改 2. 后端端口修改 (1)修改ruoyi-gateway服务中的bootstrap.yml的port端口  (2)修改ruoyi-ui中的vue.confing.js的target中的端口 3. 后端部署 (1) 在本地电脑上代码界面上打包后端 在 ruoyi 项目的 bin 目录下执行 package.bat 打包Web工程,生成jar包文件。不同模块版本会生成在

    2024年01月21日
    浏览(58)
  • ruoyi-cloud微服务新建子模块

    相关文章 官方文档 1、复制system模块 直接复制 modules下面已有的system模块,改名为 test 2、在modules下的 pom.xml文件中添加子模块 test 这里要注意添加的位置是在 modules下的 pom.xml,也就是 test的父模块的 3、进入 test模块修改 pom.xml 把原有的system 修改成test,把 modules-system修改成

    2024年02月13日
    浏览(38)
  • 若依微服务版启动(RuoYi-Cloud)教程

    之前一直有小伙伴咨询若依微服务版如何在本地启动,今天简单的给大家介绍一下。 首先,学习Java的小伙伴应该对若依框架都应该有所了解,RuoYi-Cloud 是一个 Java EE 分布式 微服务架构平台,基于经典技术组合(Spring Boot、Spring Cloud Alibaba、Vue、Element),内置模块如:部门管

    2024年01月18日
    浏览(38)
  • 基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持自定义业务表单流程(二)

    更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统      之前讲到了流程保存的时候还要看是否是自定义业务流程应用类型,若是保存的时候不再检查是否有关联表单。       那接下来就需要一个自

    2024年02月07日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包