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 {@Beanpublic ServerEndpointExporter serverEndpointExporter() {ServerEndpointExporter serverEndpointExporter = new ServerEndpointExporter();return serverEndpointExporter;}/*** 启动加载** @param servletContext*/@Overridepublic 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");}}
 @OnOpenpublic 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异常");}}@OnMessagepublic void handleMessage(Session session, String message) throws IOException {session.getBasicRemote().sendText("Reversed: " + new StringBuilder(message).reverse());}@OnClosepublic void onClose(Session session) {System.out.println("与前端断开了WebSocket连接");}@OnErrorpublic void onError(Throwable throwable) {throwable.printStackTrace();}

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

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

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

    @OnMessagepublic 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 {@Autowiredprivate SpringSocketHandle springSocketHandle;@Autowiredprivate SpringAbstractWebSocketHandler springAbstractWebSocketHandler;@Overridepublic 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*/@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {System.out.println("SpringSocketHandle, 收到新的连接: " + session.getId());}/*** 处理发送来的消息** @param session* @param message* @throws Exception*/@Overridepublic 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*/@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {System.out.println("WS 连接发生错误");}/***  连接关闭后调用** @param session* @param closeStatus* @throws Exception*/@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {System.out.println("WS 关闭连接");}/*** 支持分片消息** @return*/@Overridepublic boolean supportsPartialMessages() {return false;}

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

@Slf4j
@Component
public class SpringAbstractWebSocketHandler extends AbstractWebSocketHandler {/*** 业务service*/@Autowiredprivate IDampDatasourceInfoService dampDatasourceInfoService;@Autowiredprivate IDampAssetInfoService dampAssetInfoService;@Autowiredprivate SearchThreadPool searchThreadPool;@Autowiredprivate 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();}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wazuh环境配置和漏洞复现

1.wazuh配置 虚拟机 &#xff08;OVA&#xff09; - 替代安装 (wazuh.com)在官方网页安装ova文件 打开VMware选择打开虚拟机&#xff0c;把下载好的ova文件放入在设置网络改为NAT模式 账号:wazuh-user 密码:wazuh ip a 查看ip 启动小皮 远程连接 账号admin …

Linux部署RocketMQ并使用SpringBoot创建生产、消费者

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;RocketMQ、消息队列☀️每日 一言&#xff1a;在你心灰意冷、心烦意乱时也不要停下你的脚步&#xff01; 一、前言 RocketMQ&#xff08;Apache RocketMQ&#xff09;是一种开源的分布式消息中间…

使用Python爬虫采集网络热点

在当今信息爆炸的时代&#xff0c;了解网络热搜词和热点事件对于我们保持时事敏感性和把握舆论动向非常重要。在本文中&#xff0c;我将与你分享使用Python爬虫采集网络热搜词和热点事件的方法&#xff0c;帮助你及时获取热门话题和热点新闻。 1. 网络热搜词采集 网络热搜词是人…

JS-this知识点、面试题

一、this指向什么 1.简介 2.规则一&#xff1a;默认绑定 3.规则二&#xff1a;隐式绑定 4.规则四&#xff1a;new绑定 5.规则三&#xff1a;显式绑定 call、apply、bind 6.内置函数的绑定 7.规则优先级 8.this规则之外--es6剪头函数 9.ES6剪头函数this 二、This面试题 面试题…

学习Linux的注意事项(使用经验;目录作用;服务器注意事项)

本篇分享学习Linux过程中的一些经验 文章目录 1. Linux系统的使用经验2. Linux各目录的作用3. 服务器注意事项 1. Linux系统的使用经验 Linux严格区分大小写Linux中所有内容以文件形式保存&#xff0c;包括硬件&#xff0c;Linux是以管理文件的方式操作硬件 硬盘文件是/dev/s…

【深度学习】实验03 特征处理

文章目录 特征处理标准化归一化正则化 特征处理 标准化 # 导入标准化库 from sklearn.preprocessing import StandardScalerfrom matplotlib import gridspec import numpy as np import matplotlib.pyplot as plt import warnings warnings.filterwarnings("ignore&quo…

java练习8.100m小球落地

题目: 如一个小球从100米高度自由落下&#xff0c;每次落地后就反跳回原高度的一半。 那么求它在第10次落地时&#xff0c;共经过多少米&#xff1f;第10次反弹多高&#xff1f; public static void main(String[] args) {/*假如一个小球从100米高度自由落下&#xff0c;每次落…

【Unity开发必备】100多个 Unity 学习网址 资源 收藏整理大全【持续更新】

Unity 相关网站整理大全 众所周知&#xff0c;工欲善其事必先利其器&#xff0c;有一个好的工具可以让我们事半功倍&#xff0c;有一个好用的网站更是如此&#xff01; 但是好用的网站真的太多了&#xff0c;收藏夹都满满的(但是几乎没打开用过&#x1f601;)。 所以本文是对…

服务器的介绍

1.服务器概述 1.1 服务器的基本概念 服务器是计算机的一种&#xff0c;是网络中为客户端计算机提供各种服务的高性能计算机&#xff1b; 服务器在网络操作系统的控制下&#xff0c;将与其相连的硬盘、磁带、 打印机及昂贵的专用通讯设备提供给网络上的客户站点共享&#xf…

ISIS路由协议

骨干区域与非骨干区域 凡是由级别2组建起来的邻居形成骨干区域&#xff1b;级别1就在非骨干区域&#xff0c;骨干区域有且只有一个&#xff0c;并且需要连续&#xff0c;ISIS在IP环境下目前不支持虚链路。 路由器级别 L1路由器只能建立L1的邻居&#xff1b;L2路由器只能建立L…

软件测试的方法有哪些?

软件测试 根据利用的被测对象信息的不同&#xff0c;可以将软件测试方法分为&#xff1a;黑盒测试、灰盒测试、白盒测试。 1、白盒测试 1&#xff09;概念&#xff1a;是依据被测软件分析程序内部构造&#xff0c;并根据内部构造分析用例&#xff0c;来对内部控制流程进行测试…

【给自己挖个坑】三维视频重建(NSR技术)-KIRI Engine

文章目录 以下是我和AI的对话通过手机拍摄物体的视频&#xff0c;再根据视频生成三维模型&#xff0c;这个可实现吗我想开发类似上面的手机应用程序&#xff0c;如何开发呢 看了以上回答&#xff0c;还是洗洗睡吧NSR技术的实现原理是什么呢有案例吗我是名Java工程师&#xff0c…