springboot对接WebSocket实现消息推送

1.修改pom文件

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

2.增加配置WebSocketConfig.java

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();
    }

}

3.创建一个WebSocket实例


import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@ServerEndpoint(value = "/websocket/{name}")
@Component
public class WebSocket {
    /**
     *  与某个客户端的连接对话,需要通过它来给客户端发送消息
     */
    private Session session;

    /**
     * 标识当前连接客户端的用户名
     */
    private String name;

    /**
     *  用于存所有的连接服务的客户端,这个对象存储是安全的
     */
    private static ConcurrentHashMap<String,WebSocket> webSocketSet = new ConcurrentHashMap<>();


    @OnOpen
    public void OnOpen(Session session, @PathParam(value = "name") String name){
        this.session = session;
        this.name = name;
        // name是用来表示唯一客户端,如果需要指定发送,需要指定发送通过name来区分
        webSocketSet.put(name,this);
        log.info("[WebSocket] 连接成功,当前连接人数为:={}",webSocketSet.size());
    }


    @OnClose
    public void OnClose(){
        webSocketSet.remove(this.name);
        log.info("[WebSocket] 退出成功,当前连接人数为:={}",webSocketSet.size());
    }

    @OnMessage
    public void OnMessage(String message, @PathParam("name") String name){
        log.info("[WebSocket] 收到消息:{}",message);
        appointSending(name,message);
    }

    /**
     * 群发
     * @param message
     */
    public void groupSending(String message){
        for (String name : webSocketSet.keySet()){
            try {
                webSocketSet.get(name).session.getBasicRemote().sendText(message);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    /**
     * 指定发送
     * @param name
     * @param message
     */
    public void appointSending(String name,String message){
        try {
            WebSocket webSocket = webSocketSet.get(name);
            if(null != webSocket) {
                webSocket.session.getBasicRemote().sendText(message);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

4.修改启动类,添加注解

@EnableWebSocket

5.测试一下推送消息

Websocket在线测试-Websocket接口测试-Websocket模拟请求工具

浏览器端发送消息

服务端收到信息

6.前端对接WebSocket

    var websocket = null;
    if('WebSocket' in window){
        websocket = new WebSocket("ws://127.0.0.1:6893/websocket/1");
    }
 
    websocket.onopen = function(){
        console.log("连接成功");
    }
 
    websocket.onclose = function(){
        console.log("退出连接");
    }
 
    websocket.onmessage = function (event){
        console.log(getTime() + "收到消息: "+event.data);
        // playMp3();
        // handleSpeak(event.data);
    }
 
    websocket.onerror = function(){
        console.log("连接出错");
    }
 
    window.onbeforeunload = function () {
        websocket.close(num);
    }

    


 const getTime= () => {
    const time = new Date();
    const year = time.getFullYear();
    const month = ('0' + (time.getMonth() + 1)).slice(-2);
    const day = ('0' + time.getDate()).slice(-2);
    const hours = ('0' + time.getHours()).slice(-2);
    const minutes = ('0' + time.getMinutes()).slice(-2);
    const seconds = ('0' + time.getSeconds()).slice(-2);
    const now = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    return now;
 }

7.增加消息推送语音播放_文本转语音

     const synth = window.speechSynthesis; // 启用文本
     const msg = new SpeechSynthesisUtterance(); // 表示一次发音请求。其中包含了将由语音服务朗读的内容,以及如何朗读它(例如:语种、音高、音量)。

 // 语音播报的函数
 const handleSpeak=(text)=> {
     msg.text = text; // 文字内容: 测试内容
     msg.lang = "zh-CN"; // 使用的语言:中文
     msg.volume = 100; // 声音音量:1
     msg.rate = 1; // 语速:1
     msg.pitch = 100; // 音高:1
     synth.speak(msg); // 播放
 }; 
 // 语音停止
 const  handleStop=(e)=>  {
     msg.text = e;
     msg.lang = "zh-CN";
     synth.cancel(msg); // 取消该次语音播放
 };  
handleSpeak("测试内容");

或者播放指定的音频文件,播放音频需要浏览器设置可以发放声音,推荐一个文本转语音的网站

在线免费文字转语音 - TTSMaker官网 | 马克配音

const playMp3 = () => {
        let mp3 = new Audio('音频地址') // 创建音频对象
        mp3.loop = false;
        mp3.play() // 播放
    }

8.如何修改成wss请求

项目上线需要https请求,把请求地址换成wss,需要通过nginx配置转发,再443端口加上如下配置

location /wss/ {
        proxy_pass http://127.0.0.1:6893/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_read_timeout 18000s;
        proxy_connect_timeout 18000s;
        proxy_send_timeout 18000s;
    }

请求地址更换成wss://域名/wss/websocket/

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

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

相关文章

网络隔离后,怎样建立高效安全的数据安全交换通道?

数据安全对企业生存发展有着举足轻重的影响&#xff0c;数据资产的外泄、破坏都会导致企业无可挽回的经济损失和核心竞争力缺失。数据流动才能让其释放价值&#xff0c;想要保护企业核心资产&#xff0c;就要实现数据安全交换。 很多企业为了防止知识产权、商业机密数据泄露&am…

2023安洵杯-秦岭防御军wp

reverse 感觉有点点简单## import base64 def ba64_decode(str1_1):mapp "4KBbSzwWClkZ2gsr1qAQu0FtxOm6/iVcJHPY9GNp7EaRoDf8UvIjnL5MydTX3eh"data_1 [0] * 4flag_1 [0] * 3for i in range(32, 127):for y in range(32, 127):for k in range(32, 127):flag_1[0]…

【目标跟踪】解决多目标跟踪遮挡问题

文章目录 前言一、判定遮挡目标二、扩展目标框三、结论 前言 目标跟踪在发生遮挡时&#xff0c;极其容易发生Id Switch。网上许多算法忽视跟踪遮挡问题,同时网上相关资料也很少。博主为了解决跟踪遮挡&#xff0c;翻阅大量论文。分享其中一篇论文。论文链接&#xff1a;https:…

dl转置卷积

转置卷积 转置卷积&#xff0c;顾名思义&#xff0c;通过名字我们应该就能看出来&#xff0c;其作用和卷积相反&#xff0c;它可以使得图像的像素增多 上图的意思是&#xff0c;输入是22的图像&#xff0c;卷积核为22的矩阵&#xff0c;然后变换成3*3的矩阵 代码如下 import…

Python 运维(四):使用 PyInstaller 将 Python 程序打包成可执行文件

大家好&#xff0c;我是水滴~~ PyInstaller是一款强大的Python打包工具&#xff0c;通过将Python程序转换成可执行文件&#xff0c;它简化了程序的分享和分发过程。本文从简介、安装、使用以及典型案例四个方面对PyInstaller进行了介绍。 文章内容包含大量的示例代码&#xf…

Vue学习之第一、二章——Vue核心与组件化编程

第一章. Vue核心 1.1 Vue简介 1.1.1 官网 英文官网: https://vuejs.org/中文官网: https://cn.vuejs.org/ 1.1.2 Vue特点 遵循 MVVM 模式编码简洁, 体积小, 运行效率高, 适合移动/PC 端开发它本身只关注 UI, 也可以引入其它第三方库开发项目 1.2 初始Vue 这里可以参考&a…

uni-app 命令行创建

1. 首先创建项目&#xff0c;命令如下: npx degit dcloudio/uni-preset-vue#vite-ts uni-app-demo如果出现报错&#xff0c;如下图. 大概率就是没有目录C:\Users\Administrator\AppData\Roaming\npm 解决办法&#xff1a; 创建目录 C:\Users\Administrator\AppData\Roaming\n…

关于Zoom ZTP和AudioCodes Ltd桌面电话缺陷暴露,导致用户遭受窃听的动态情报

一、基本内容 近期SySS安全研究员发布分析报告显示&#xff0c;Zoom的零接触&#xff08;ZTP&#xff09;和AudioCodes Ltd桌面电话配置功能中发现高危漏洞&#xff0c;可以获得对设备的完全远程控制并不受限制的访问可以被武器化&#xff0c;以窃听房间或电话、通过设备并攻击…

LazyForEach常见使用问题

目录 1、渲染结果非预期 2、重新渲染时图片闪烁 3、ObjectLink属性变化UI未更新 上篇文章中我们介绍了LazyForEach的基本使用&#xff0c;展示了如何使用LazyForEach构造一个列表&#xff0c;并演示数据的添加、删除、修改如何与LazyForEach配合并正确的更新UI。本篇将介绍使…

【kafka消息里会有乱序消费的情况吗?如果有,是怎么解决的?】

文章目录 什么是消息乱序消费了&#xff1f;顺序生产&#xff0c;顺序存储&#xff0c;顺序消费如何解决乱序数据库乐观锁是怎么解决这个乱序问题吗 保证消息顺序消费两种方案固定分区方案乐观锁实现方案 前几天刷着视频看见评论区有大佬问了这个问题&#xff1a;你们的kafka消…

策略模式(组件协作)

策略模式&#xff08;组件协作&#xff09; 链接&#xff1a;策略模式实例代码 注解 目的 正常情况下&#xff0c;一个类/对象中会包含其所有可能会使用的内外方法&#xff0c;但是一般情况下&#xff0c;这些常使用的类都是由不同的父类继承、组合得来的&#xff0c;来实现…

《软件需求分析报告》

第1章 序言 第2章 引言 2.1 项目概述 2.2 编写目的 2.3 文档约定 2.4 预期读者及阅读建议 第3章 技术要求 3.1 软件开发要求 第4章 项目建设内容 第5章 系统安全需求 5.1 物理设计安全 5.2 系统安全设计 5.3 网络安全设计 5.4 应用安全设计 5.5 对用户安全管理 …

创建servlet的三种方式

目录 ​编辑 1.实现Servlet接口的方式 2.继承GenericServlet抽象类的方式 3.继承HttpServlet的方式 1.实现Servlet接口的方式 因为是实现 Servlet 接口&#xff0c;所以我们需要实现接口里的方法。 import javax.servlet.*; import javax.servlet.annotation.WebServlet;…

DS八大排序之归并排序和计数排序

前言 前几期我们详细介绍了插入排序&#xff08;直接插入排序和希尔排序&#xff09;、选择排序&#xff08;直接选择和堆排序&#xff09;、交换排序&#xff08;冒泡排序和快速排序&#xff09;。并对快排的各个版本做了详细的介绍&#xff0c;本期我们来介绍把最后两个即外…

k8s面试之——简述网络模型

kubernetes网络模型是kubernetes集群中管理容器网络通信的一种机制&#xff0c;用于实现pod间、pod与外部网络间的通信和互联&#xff0c;并提供了多种网络插件和配置选项来满足不同应用场景下的需求。kubernetes网络模型可以分为一下几个部分&#xff1a; 1. pod网络模型 在…

经典文献阅读之--OccNeRF(基于神经辐射场的自监督多相机占用预测)

0. 简介 作为基于视觉感知的基本任务&#xff0c;3D占据预测重建了周围环境的3D结构。它为自动驾驶规划和导航提供了详细信息。然而&#xff0c;大多数现有方法严重依赖于激光雷达点云来生成占据地面真实性&#xff0c;而这在基于视觉的系统中是不可用的。之前我们介绍了《经典…

cephfs cap机制介绍

一、Cap&#xff1a;概述 cap是文件系统层面的&#xff0c;包括元数据、数据操作。cap 和mds分布式锁是对应的cap是MDS分配给client对inode的操作能力权限。不同的客户端&#xff0c;或者同一客户端不同时刻&#xff0c;对同一inode持有cap可能是不同的•作用&#xff1a;MDS通…

学习笔记13——Spring整合Mybatis、junit、AOP、事务

学习笔记系列开头惯例发布一些寻亲消息 链接&#xff1a;https://baobeihuijia.com/bbhj/ Mybatis - Spring&#xff08;使用第三方包new一个对象bean&#xff09; 原始的Mybatis与数据库交互【通过sqlmapconfig来配置和连接】 初始化SqlSessionFactory获得连接获取数据层接口…

Python pandas 操作 excel 详解

文章目录 1 概述1.1 pandas 和 openpyxl 区别1.2 Series 和 DataFrame 2 常用操作2.1 创建 Excel&#xff1a;to_excel()2.2 读取 Excel&#xff1a;read_excel()2.2.1 header&#xff1a;标题的行索引2.2.2 index_col&#xff1a;索引列2.2.3 dtype&#xff1a;数据类型2.2.4 …

ansible 备忘清单(一)

笔者&#xff1a; 把以前的手写笔记电子化吧&#xff0c;顺便当作复习。 基础命令 命令 参数 备注 ansible --version 查看版本号 ansible-doc --help 查看帮助信息 -l &#xff5c;--list 查看所有模块 -s 查看模块摘要 Ansible servers -I &#xff5c;-…