WebStock会话

ops/2024/9/23 9:37:00/

其实使用消息队列也可以实现会话,直接前端监听指定的队列,使用rabbitmq的分组还可以实现不同群聊的效果。

1、依赖搭建:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>WebStock</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.8</version><relativePath/></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties></project>

SpringBoot都已集成完毕了,不用使用原生的WebStock。

2、配置运行

如果是工作中,要单独起一个服务来操作这个比较好,反正是微服务,多一个少一个没啥的

WebStock连接配置、

java">package com.quxiao.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;import java.time.LocalDateTime;/*** ws消息处理类*/
@Component
@Slf4j
public class MyWsHandler extends AbstractWebSocketHandler {@AutowiredWsService wsService;@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {log.info("建立ws连接");WsSessionManager.add(session.getId(), session);}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {log.info("发送文本消息");// 获得客户端传来的消息String payload = message.getPayload();//这里也是一样,要取出前端传来的参数,判断发给谁.这里我就是发给了连接客户端自己.log.info("server 接收到消息 " + payload);wsService.sendMsg(session, "server 发送给的消息 " + payload + ",发送时间:" + LocalDateTime.now().toString());String url = session.getUri().toString();//使用?拼接参数,后端取出判断发给谁System.out.println("获取到的参数:" + url.substring(url.indexOf('?') + 1));}@Overrideprotected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {log.info("发送二进制消息");}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {log.error("异常处理");WsSessionManager.removeAndClose(session.getId());}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {log.info("关闭ws连接");WsSessionManager.removeAndClose(session.getId());}
}
java">package com.quxiao.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.WebSocketSession;import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;@Slf4j
public class WsSessionManager {/*** 保存连接 session 的地方*/public  static ConcurrentHashMap<String, WebSocketSession> SESSION_POOL = new ConcurrentHashMap<>();/*** 添加 session** @param key*/public static void add(String key, WebSocketSession session) {// 添加 sessionSESSION_POOL.put(key, session);}/*** 删除 session,会返回删除的 session** @param key* @return*/public static WebSocketSession remove(String key) {// 删除 sessionreturn SESSION_POOL.remove(key);}/*** 删除并同步关闭连接** @param key*/public static void removeAndClose(String key) {WebSocketSession session = remove(key);if (session != null) {try {// 关闭连接session.close();} catch (IOException e) {// todo: 关闭出现异常处理e.printStackTrace();}}}/*** 获得 session** @param key* @return*/public static WebSocketSession get(String key) {// 获得 sessionreturn SESSION_POOL.get(key);}
}
java">package com.quxiao.config;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;@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Autowiredprivate MyWsHandler myWsHandler;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(myWsHandler, "myWs")//允许跨域.setAllowedOrigins("*");}
}

这里有几个后续逻辑:

(1)、连接时,通过前端的参数或者对其按登陆人信息绑定连接消息。

(2)、收到一个消息,发送给谁就得需要前端传来参数:例如某个群的id,然后通过群绑定人员,因为(1)中通过<key,value>人员id为key,value时连接信息。

直接遍历这个群下面的所有人员id,获取已经连接的信息,发送给他们。这里还要搞一个表存储群消息log。这样其他群员连接时,可以获取到以往的消息。

发送消息工具类

java">package com.quxiao.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;import java.io.IOException;/*** ws操作相关服务*/
@Service
@Slf4j
public class WsServiceUtil {/*** 发送消息* @param session* @param text* @return* @throws IOException*/public void sendMsg(WebSocketSession session, String text) throws IOException {session.sendMessage(new TextMessage(text));}/*** 广播消息* @param text* @return* @throws IOException*/public void broadcastMsg(String text) throws IOException {for (WebSocketSession session: WsSessionManager.SESSION_POOL.values()) {session.sendMessage(new TextMessage(text));}}}

   这里广播我就是遍历了储存连接消息的map容器。

java">package com.quxiao.controller;import com.quxiao.config.WsServiceUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;@RestController
@RequestMapping("/put")
public class MessageHandler {@AutowiredWsServiceUtil wsServiceUtil;@PostMapping("/t1/{test}")public void t1(@PathVariable("test") String text) {try {wsServiceUtil.broadcastMsg(Thread.currentThread().getName() + ": " + text);} catch (Exception e) {throw new RuntimeException(e);}}}

3、 前端测试页面:

<!DOCTYPE HTML>
<html>
<head><title>My WebSocket</title>
</head><body>
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message"></div></body><script type="text/javascript">let ws = null;//判断当前浏览器是否支持WebSocketif ('WebSocket' in window) {ws = new WebSocket("ws://localhost:8080/myWs?2002");}else {alert('当前浏览器 Not support websocket')}//连接发生错误的回调方法ws.onerror = function () {setMessageInnerHTML("WebSocket连接发生错误");};//连接成功建立的回调方法ws.onopen = function(event) {console.log("ws调用连接成功回调方法")//ws.send("")}//接收到消息的回调方法ws.onmessage = function(message) {console.log("接收消息:" + message.data);if (typeof(message.data) == 'string') {setMessageInnerHTML(message.data);}}//ws连接断开的回调方法ws.onclose = function(e) {console.log("ws连接断开")//console.log(e)setMessageInnerHTML("ws close");}//将消息显示在网页上function setMessageInnerHTML(innerHTML) {console.log(innerHTML)document.getElementById('message').innerHTML += '接收的消息:' + innerHTML + '<br/>';}//关闭连接function closeWebSocket() {ws.close();}//发送消息function send(msg) {if(!msg){msg = document.getElementById('text').value;document.getElementById('message').innerHTML += "发送的消息:" + msg + '<br/>';ws.send(msg);}}
</script>
</html>

4、总结

所以最重要的是这个消息发给谁

        后端要做的就是需要根据不同的群、人员标识符去发送消息,

前端需要做的就是

        传入不同的标识符,如果是私聊,就得传人员id,如果是群聊,就需要传入群id。


http://www.ppmy.cn/ops/88964.html

相关文章

Docker Image即Docker镜像

Docker Image&#xff0c;即Docker镜像&#xff0c;是Docker技术中的核心概念之一&#xff0c;它扮演着容器化应用程序打包和分发的重要角色。下面将详细讲解Docker镜像的定义、特点、构成、操作以及应用场景等方面。 一、Docker镜像的定义 Docker镜像是一种轻量级、可移植的…

界面控件DevExpress WinForms,支持HTML CSS提升用户体验(一)

DevExpress WinForms现在可以利用HTML/CSS强大的功能&#xff0c;帮助受DevExpress驱动的WinForms应用程序引入现代的UI元素和用户体验&#xff01; P.S&#xff1a;DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。Dev…

如何将WordPress文章中的外链图片批量导入到本地

在使用采集软件进行内容创作时&#xff0c;很多文章中的图片都是远程链接&#xff0c;这不仅会导致前端加载速度慢&#xff0c;还会在微信小程序和抖音小程序中添加各种域名&#xff0c;造成管理上的麻烦。特别是遇到没有备案的外链&#xff0c;更是让人头疼。因此&#xff0c;…

Python:range()函数的用法

range() 函数是 Python 中一个内置函数&#xff0c;用于生成一个数字序列。这个函数通常用于在 for 循环中迭代一个指定的次数。range() 函数可以接收一到三个参数&#xff0c;分别是起始值&#xff08;start&#xff09;、结束值&#xff08;stop&#xff09;和步长&#xff0…

C# 代码适配 Python

C# if obj is Type obj_1Python if isinstance(obj, Type):

设计模式——动态代理

设计模式——动态代理 动态代理的基本概念动态代理的实现步骤总结 在Java中&#xff0c;动态代理是一种强大的机制&#xff0c;它允许在运行时创建一个代理对象&#xff0c;这个代理对象可以代表另一个实际对象&#xff0c;它允许你在不直接操作原始对象的情况下&#xff0c;通…

力扣:3128. 直角三角形(Java)

目录 题目描述&#xff1a;示例 &#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给你一个二维 boolean 矩阵 grid 。 请你返回使用 grid 中的 3 个元素可以构建的 直角三角形 数目&#xff0c;且满足 3 个元素值 都 为 1 。 注意&#xff1a; 如果 grid 中 3 个元素满…

filebeat发送日志

filebeat: 1.可以在本机收集日志 2.也可以远程收集日志 3.轻量级的日志收集系统&#xff0c;可以在非Java环境运行 logstash是在jvm环境中运行&#xff0c;资源消耗很高&#xff0c;启动一个logstash需要消耗500M左右的内存 filebeat只消耗10M左右的内存 test3是装有logstash的…