springboot对接WebSocket实现消息推送

news2024/11/18 23:49:58

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/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

接口测试工具——ApiFox使用初体验 postman导出和ApiFox导入

目录 ApiFox使用初体验初步使用从postman导出到apifox导入 IDEA简单测试Postman测试工具post请求 接口测试工具swaggerKnife4j1.引入依赖2.配置3.常用注解4.接口测试 JMeter什么是JMeter?JMeter安装配置1.官网下载2.下载后解压3.汉语设置 JMeter的使用方法1.新建线程组2.设置参…

智能监控平台/视频共享融合系统EasyCVR海康设备国标GB28181接入流程

TSINGSEE青犀视频监控汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力&…

基于springboot的数码论坛系统设计与实现

** &#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;** 摘 要 网络的广泛应用给…

laravel api资源的问题记录

resource 转换层 可以帮助我们转换一些字段的结果&#xff0c;类似前端的filter。 可以使用比如对象或者模型的形式来处理&#xff0c;但使用sql查询会导致n1的问题。如图&#xff1a; 层次嵌套很多&#xff0c;而且很深&#xff0c;这样虽然开发方便了&#xff0c;但是维护就…

Mysql(5日志备份恢复)

一.日志管理 MySQL 的日志默认保存位置为 /usr/local/mysql/data 先看下mysql的日志文件有无&#xff1a; 修改配置文件添加&#xff1a;错误日志&#xff0c;用来记录当MySQL启动、停止或运行时发生的错误信息&#xff0c;默认已开启 修改配置文件添加&#xff1a;通用查…

PWR 电源控制-stm32入门

这一节我们来学习 STM32 的 PWR 电源控制。 其中&#xff0c;我们重点学习的主要就是 3 种低功耗模式&#xff1a;睡眠模式、停机模式和待机模式。 低功耗模式的目的呢&#xff1f;简单明了&#xff0c;就是省电&#xff0c;这对于一些使用电池供电&#xff0c;又需要长时间待…

腾讯云4核8G服务器轻量和CVM标准型S5对比

腾讯云4核8G服务器优惠价格表&#xff0c;云服务器CVM标准型S5实例4核8G配置价格15个月1437.3元&#xff0c;5年6490.44元&#xff0c;轻量应用服务器4核8G12M带宽一年446元、529元15个月&#xff0c;阿腾云atengyun.com分享腾讯云4核8G服务器详细配置、优惠价格及限制条件&…

nodejs微信小程序+python+PHP基于Android自习室管理系统的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

基于ssm的电影评论系统论文

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装电影评论系统软件来发挥其高效地信息处理的作用&#xff0c…

电商低价 窜货问题怎么解决

渠道中最常见的问题一般都是围绕价格的&#xff0c;低价、窜货、假货问题尤为明显&#xff0c;经销商为了利益&#xff0c;总会进行价格的突破&#xff0c;窜货也是为了获得更多流量利润&#xff0c;也会变相低价&#xff0c;所以治理好低价、窜货问题&#xff0c;就是在管控渠…

【LeetCode刷题笔记(13-1)】【Python】【回文数】【反转整数】【简单】

文章目录 引言回文数题目描述提示 题意分析解决方案1&#xff1a;【反转字符串】解决方案2&#xff1a;【反转整数】题外话结束语 9. 回文数 引言 编写通过所有测试案例的代码并不简单&#xff0c;通常需要深思熟虑和理性分析。虽然这些代码能够通过所有的测试案例&#xff0…

[PyTorch][chapter 8][李宏毅深度学习][DNN 训练技巧]

前言&#xff1a; DNN 是神经网络的里面基础核心模型之一.这里面结合DNN 介绍一下如何解决 深度学习里面过拟合,欠拟合问题 目录&#xff1a; DNN 训练常见问题 过拟合处理 欠拟合处理 keras 项目 一 DNN 训练常见问题 我们在深度学习网络训练的时候经常会遇到下面…

Android原生实现分段选择

六年前写的一个控件&#xff0c;一直没有时间总结&#xff0c;趁年底不怎么忙&#xff0c;整理一下之前写过的组件。供大家一起参考学习。废话不多说&#xff0c;先上图。 一、效果图 实现思路使用的是radioGroup加radiobutton组合方式。原理就是通过修改RadioButton 的backgr…

什么是EMC工程师?

摘要: 今天来介绍一下什么是EMC工程师。一 EMC工程师起源要了解什么是EMC工程师&#xff0c;我们首先要了解什么是EMC。 今天来介绍一下什么是EMC工程师。 一 EMC工程师起源 要了解什么是EMC工程师&#xff0c;我们首先要了解什么是EMC。 工程师这个职业相信大家都耳熟能详…

Android10.0 人脸解锁流程分析

人脸解锁概述 人脸解锁即用户通过注视设备的正面方便地解锁手机或平板。Android 10 为支持人脸解锁的设备在人脸认证期间添加了一个新的可以安全处理相机帧、保持隐私与安全的人脸认证栈的支持&#xff0c;也为安全合规地启用集成交易的应用&#xff08;网上银行或其他服务&am…

华为OD机试 - 推荐多样性(Java JS Python C)

题目描述 推荐多样性需要从多个列表中选择元素,一次性要返回 N 屏数据(窗口数量),每屏展示 K 个元素(窗口大小),选择策略: 各个列表元素需要做穿插处理,即先从第一个列表中为每屏选择一个元素,再从第二个列表中为每屏选择一个元素,依次类推每个列表的元素尽量均分为…

wireshark access/trunk/hybrid报文分析

1&#xff0c;access接口 发送带vlan的报文 wireshark交换机配置 [Huawei-GigabitEthernet0/0/1] [Huawei-GigabitEthernet0/0/1]port link-type access [Huawei-GigabitEthernet0/0/1]port default vlan 100 [Huawei-GigabitEthernet0/0/2]port link-type access [Huawei-Gig…

前端开发之通过vue-office组件实现文件预览

前端开发之通过vue-office组件实现文件预览 前言效果图docx文件xlsx文件pdf文件 vue中简单案例1、安装组件2、vue中代码 前言 在实现文件预览的时候我们可以通过vue-office组件来实现文件的预览效果 效果图 docx文件 xlsx文件 pdf文件 vue中简单案例 1、安装组件 整体安装…

LoongArch指令集-特权指令系统——摘抄自胡伟武体系结构和龙芯架构32位精简版参考手册

例外与中断 1 中断 1.1 中断类型 龙芯架构 32 位精简版下的中断采用线中断的形式。每个处理器核内部可记录 12 个线中断&#xff0c;分别是&#xff1a;1 个核间中断&#xff08;IPI&#xff09;&#xff0c;1 个定时器中断&#xff08;TI&#xff09;&#xff0c;8 个硬中断…

Muscles|Tissue —— Workflow

目录 Muscles pass Tissue pass Skin pass Simulation transfer Muscles pass Muscles & Tissue的第一阶段内&#xff0c;为模拟创建muscle pass&#xff0c;会创建solid肌肉几何体&#xff08;用动画骨骼移动和弯曲&#xff09;&#xff0c;然后驱动下游组织的大部分变…