spring boot 项目整合 websocket

1.业务背景

        负责的项目有一个搜索功能,搜索的范围几乎是全表扫,且数据源类型贼多。目前对搜索的数据量量级未知,但肯定不会太少,不仅需要搜索还得点击下载文件。

 

        关于搜索这块类型 众多,未了避免有个别极大数据源影响整个搜索效率,我采用多线程异步搜索,将搜索到每个数据源数据使用 websocket 响应给前端。

2.遇到的问题

        1 .想自定义接收前端消息的类型,因为接收的消息类型都是string 类型,所以一看肯定不符合我的需求。(唉,怪我没多问)

          思路: 其实接收是string一点不影响。直接上json,转对象就行。

        2. socket 什么时候关闭 

          思路:

                    1.心跳包检测,心跳达到次数断开socket。(前后端互发心跳)

                    2. 因为多线程,后端开启线程监听线程有没有执行完的队列还有没有还没执行的任务,没有开始计时,达到时间关闭socket,若计时期间有任务重置计时。(后端监听)

3.相关资料

一文搞懂四种 WebSocket 使用方式_@enablewebsocket_Java架构狮的博客-CSDN博客

4.代码实现

        1.注解写法

/**
 * 开启WebSocket支持
 * Created by huiyunfei on 2019/5/31.
 */
@Configuration
@EnableWebSocket
public class WebSocketConfig implements ServletContextInitializer {


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


    /**
     * 启动加载
     *
     * @param servletContext
     */
    @Override
    public void onStartup(ServletContext servletContext) {
        servletContext.addListener(WebAppRootListener.class);

        // 接收base64的字符串,等于50M  解决上传内容过大问题
        servletContext.setInitParameter("org.apache.tomcat.websocket.textBufferSize", "52428800");
        servletContext.setInitParameter("org.apache.tomcat.websocket.binaryBufferSize", "52428800");
    }


}
 @OnOpen
    public void onOpen(Session session) {
        System.out.println("与前端建立了WebSocket连接");
        this.session = session;
        webSocketSet.add(this);     //加入set中
//        addOnlineCount();           //在线数加1
//        log.info("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount());
        this.sid=sid;

        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.error("websocket IO异常");
        }
    }


    @OnMessage
    public void handleMessage(Session session, String message) throws IOException {
        session.getBasicRemote().sendText("Reversed: " + new StringBuilder(message).reverse());

    }



    @OnClose
    public void onClose(Session session) {
        System.out.println("与前端断开了WebSocket连接");
    }

    @OnError
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
    }

       注意:谁说是注解开发,切记并不是发送http请求,下面是错误实例

        上面我不是提到想自定义接收参数,然后我一直以为加个注解就行。接收类型别动。

         不然就像苦逼的我程序都启动不了,排错半天时间。

    @OnMessage
    public void onMessage(Session session, FullSearchParam param) {
        System.out.println("接收到前端发送的消息:" + param.getSearchContext());
        try {
//            fullSearch(param, session);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (EncodeException e) {
            throw new RuntimeException(e);
        }
    }

        2.实现接口

package com.trinity.web.controller.search.spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;


/**
 * 开启WebSocket支持
 * Created by huiyunfei on 2019/5/31.
 */
@Configuration
@EnableWebSocket
public class SpringSocketConfig implements WebSocketConfigurer {

    @Autowired
    private SpringSocketHandle springSocketHandle;

    @Autowired
    private SpringAbstractWebSocketHandler springAbstractWebSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(springSocketHandle, "/spring-ws").setAllowedOrigins("*")
                .addHandler(springAbstractWebSocketHandler, "/spring-ws1").setAllowedOrigins("*");
    }



}

              这种方式接收消息需要判断,因为 WebSocketMessage 是接口,spring 提供了三个实现类,分别是文本 字节 ping,目前后两种还不知道怎么使用。所以这种方式需要区判断前端传输的数据类型分别处理。

@Component
public class SpringSocketHandle implements WebSocketHandler {

    /**
     * 连接成功后调用。
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("SpringSocketHandle, 收到新的连接: " + session.getId());
    }

    /**
     * 处理发送来的消息
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String msg = "SpringSocketHandle, 连接:" + session.getId() +  ",已收到消息。";
        System.out.println(msg);
//        this.handleMessage(session, );
        session.sendMessage(new TextMessage(msg));
    }

    /**
     * WS 连接出错时调用
     *
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("WS 连接发生错误");
    }

    /**
     *  连接关闭后调用
     *
     * @param session
     * @param closeStatus
     * @throws Exception
     */

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        System.out.println("WS 关闭连接");
    }

    /**
     * 支持分片消息
     *
     * @return
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

        这种方式就更加简单不需要我们自己去判断

@Slf4j
@Component
public class SpringAbstractWebSocketHandler extends AbstractWebSocketHandler {

    /**
     * 业务service
     */
    @Autowired
    private IDampDatasourceInfoService dampDatasourceInfoService;
    @Autowired
    private IDampAssetInfoService dampAssetInfoService;
    @Autowired
    private SearchThreadPool searchThreadPool;
    @Autowired
    private TokenService tokenService;


    /**
     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlineCount = 0;

    /**
     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     */
    private static CopyOnWriteArraySet<SearchSocketServer> webSocketSet = new CopyOnWriteArraySet<SearchSocketServer>();

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


    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("接收到搜索的消息,搜索内容为{}",message);
        List<String> authorization = session.getHandshakeHeaders().get("Authorization");
        FullSearchParam param = JSONObject.parseObject(message.getPayload(), FullSearchParam.class);
        fullSearch(param, session);
    }



    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {

    }

    protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
    }

      5.总结

        尝试写不会的代码总是非常的认真,但也非常煎熬。

        然后接收消息时用到了 SecurityUtils 公共方法 从token 获取用户id,但是却出现获取失败。

        明天再看

public class SecurityUtils
{
    /**
     * 用户ID
     **/
    public static Long getUserId()
    {
        try
        {
            return getLoginUser().getUserId();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
        }
    }
/**
     * 获取用户
     **/
    public static LoginUser getLoginUser()
    {
        try
        {
            return (LoginUser) getAuthentication().getPrincipal();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * 获取Authentication
     */
    public static Authentication getAuthentication()
    {
        return SecurityContextHolder.getContext().getAuthentication();
    }

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

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

相关文章

Maven之高版本的 lombok 和 tomcat 7 插件冲突问题

高版本的 lombok 和 tomcat 7 插件冲突问题 在开发期间&#xff0c;当我们使用 tomcat7-maven-plugin 来作为运行环境运行我们项目使&#xff0c;如果我们项目中使用了 1.16.20 及以上版本的 lombok 包&#xff0c;项目启动时会报错&#xff1a; for annotations org.apache.…

ELK之LogStash介绍及安装配置

一、logstash简介 集中、转换和存储数据 Logstash 是免费且开放的服务器端数据处理管道&#xff0c;能够从多个来源采集数据&#xff0c;转换数据&#xff0c;然后将数据发送到您最喜欢的“存储库”中。 Logstash 能够动态地采集、转换和传输数据&#xff0c;不受格式或复杂度的…

完美解决Ubuntu网络故障,连接异常,IP地址一直显示127.0.0.1

终端输入ifconfig显示虚拟机IP地址为127.0.0.1&#xff0c;具体输出内容如下&#xff1a; wxyubuntu:~$ ifconfig lo: flags73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0inet6 ::1 prefixlen 128 scopeid 0x10<host>loop txqueuelen …

【VMware】CentOS 设置静态IP(Windows 宿主机)

文章目录 1. 更改网络适配器设置2. 配置虚拟网络编辑器3. 修改 CentOS 网络配置文件4. ping 测试结果 宿主机&#xff1a;Win11 22H2 虚拟机&#xff1a;CentOS-Stream-9-20230612.0 (Minimal) 1. 更改网络适配器设置 Win R&#xff1a;control 打开控制面板 依次点击&#x…

【IMX6ULL驱动开发学习】09.Linux之I2C驱动框架简介和驱动程序模板

参考&#xff1a;Linux之I2C驱动_linux i2c驱动_风间琉璃•的博客-CSDN博客​​​​​​ 目录 一、I2C驱动框架简介 1.1 I2C总线驱动 1.2 I2C设备驱动 二、I2C总线-设备-驱动模型 2.1 i2c_driver 2.2 i2c_client 2.3 I2C 设备数据收发和处理 三、Linux I2C驱动程序模板…

华为数通方向HCIP-DataCom H12-821题库(单选题:61-80)

第61题 关于 BGP 的Keepalive报文消息的描述,错误的是 A、Keepalive周期性的在两个BGP邻居之间发送 B、Keepalive报文主要用于对等路由器间的运行状态和链路的可用性确认 C、Keepalive 报文只包含一个BGP数据报头 D、缺省情况下,Keepalive 的时间间隔是180s 答案&#xff…

【RISC-V】RISC-V寄存器简介

一、通用寄存器 32位RISC-V体系结构提供32个32位的整型通用寄存器寄存器别名全称说明X0zero零寄存器可做源寄存器(rs)或目标寄存器(rd)X1ra链接寄存器保存函数返回地址X2sp栈指针寄存器指向栈的地址X3gp全局寄存器用于链接器松弛优化X4tp线程寄存器常用于在OS中保存指向进程控…

【安全】原型链污染 - Code-Breaking 2018 Thejs

目录 准备工作 环境搭建 加载项目 复现 代码审计 payload 总结 准备工作 环境搭建 Nodejs BurpSuite 加载项目 项目链接 ① 下载好了cmd切进去 ② 安装这个项目 可以检查一下 ③运行并监听 可以看到已经在3000端口启动了 复现 代码审计 const fs require(fs) cons…

Streamlit 讲解专栏(十一):数据可视化-图表绘制详解(中)

文章目录 1 前言2 绘制交互式散点图3 定制图表主题4 增强数据可视化的交互性与注释步骤1步骤二 5 结语 1 前言 在上一篇博文《 Streamlit 讲解专栏&#xff08;十&#xff09;&#xff1a;数据可视化-图表绘制详解&#xff08;上&#xff09;》中&#xff0c;我们学习了一些关…

开源项目-数据可视化分析平台

哈喽,大家好,今天给大家带来一个开源项目-数据可视化分析平台。项目通过SpringBoot实现 数据可视化分析平台主要有数据源管理,项目管理,数据集管理,图表管理,看板管理等功能 登录 数据源管理 数据源管理功能可以添加MySQL,Oracle,PostgreSQL等类型的数据源信息 项目…

Unity OnDrawGizmos的简单应用 绘制圆形

编辑器和配置表各有各的好。 卡牌游戏即使再复杂&#xff0c;哪怕是梦幻西游&#xff0c;大话西游那种&#xff0c;甚至wow那种&#xff0c;用配表都完全没问题。但是崩坏3&#xff0c;或者鬼泣&#xff0c;格斗游戏&#xff0c;可视化编辑器是唯一的选择。 开发初期刚开始配技…

学习创建第一个 React 项目

目标 本篇的目标是配置好基础的环境并创建出第一个 React 项目。 由于之前没接触过相关的知识&#xff0c;所以还需要了解其依赖的一些概念。 步骤主要参考First React app using create-react-app | VS code | npx | npm - YouTube 0. 简单了解相关概念 JavaScript 一种语…

kali 2023.3新增工具

在终端模拟器中运行 sudo apt update && sudo apt full-upgrade 命令来更新其安装 Kali Linux 2023.3 发布中包含了九个新工具&#xff0c;分别是&#xff1a; Calico&#xff1a;云原生网络和网络安全。 cri-tools&#xff1a;用于Kubelet容器运行时接口的命令行界面…

【马拉车算法/动态规划】最长回文字串

最长回文字串 1.问题描述2.中心扩展法&#xff08;O(N^2)&#xff09;3.动态规划4.Manacher(马拉车算法) 1.问题描述 常用有3种算法&#xff1a;中心扩展法、动态规划和Manacher算法 2.中心扩展法&#xff08;O(N^2)&#xff09; 解释&#xff1a; 从中心向外扩展。 分为两种…

【C++进阶(二)】STL大法--vector的深度剖析以及模拟实现

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; vector 1. 前言2. 熟悉vector的接口函数2.1 vec…

微服务中间件--多级缓存

多级缓存 多级缓存a.JVM进程缓存1) Caffeine2) 案例 b.Lua语法1) 变量和循环2) 条件控制、函数 c.多级缓存1) 安装OpenResty2) 请求参数处理3) 查询Tomcat4) Redis缓存预热5) 查询Redis缓存6) Nginx本地缓存 d.缓存同步1) 数据同步策略2) 安装Canal2.a) 开启MySQL主从2.b) 安装…

【动手学深度学习】--21.锚框

锚框 学习视频&#xff1a;锚框【动手学深度学习v2】 官方笔记&#xff1a;锚框 1.锚框 目标检测算法通常会在输入图像中采样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界从而更准确地预测目标的真实边界框&#xff08;gro…

6个最受欢迎的3D点云查看工具【在线/离线】

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 免费3D点云软件有点像寻找大脚怪… 性质神秘。 模糊的目击。 有些人甚至认为这是民间传说。 但令人惊讶的是&#xff0c;免费的3D点云软件确实存在。 与大脚野人不同的是&#xff0c;我们已经证明了它的存在。 本文将介…

spark中排查Premature EOF: no length prefix available

报错信息 /07/22 10:20:28 WARN DFSClient: Error Recovery for block BP-888461729-172.16.34.148-1397820377004:blk_15089246483_16183344527 in pipeline 172.16.34.64:50010, 172.16.34.223:50010: bad datanode 172.16.34.64:50010 [DataStreamer for file /bdp/data/u9…

YOLOv5、v8改进:CrissCrossAttention注意力机制

目录 1.简介 2. yolov5添加方法&#xff1a; 2.1common.py构建CrissCrossAttention模块 2.2yolo.py中注册 CrissCrossAttention模块 2.3修改yaml文件。 1.简介 这是ICCV2019的用于语义分割的论文&#xff0c;可以说和CVPR2019的DANet遥相呼应。 和DANet一样&#xff0c;…