SpringBoot整合WebSocket实现订阅消息推送

目录

  • 一、什么是WebSocket
    • 1.HTTP协议
    • 2.WebSocket协议
  • 二、WebSocket使用场景
    • 1.消息推送
    • 2.实时聊天
    • 3.弹幕
    • 4.实时数据更新
  • 三、SpringBoot整合WebSocket(以实现消息推送为例)
    • 1.添加依赖
    • 2.创建消息类
    • 2.WebSocket配置类
    • 3.工具类
    • 4.测试连接
    • 5.服务调用

一、什么是WebSocket

1.HTTP协议

Http协议是一种无状态的超文本传输协议,由客户端向服务器发送请求,服务器向客户端发出响应,特点是一问一答的形式,如果需要服务端主动向客户端发送消息就不适用了。
在这里插入图片描述

2.WebSocket协议

WebSocket是一种计算机通信协议,通过单个 TCP 连接提供双向数据传输的协议。

  • 双向性: 使用 WebSocket 客户端或服务器可以发起消息发送,不必像Http协议,只能由客户端发起请求,因此WebSocket适合服务器单方向客户端发起推送的业务场景。
  • 轻量级: 与 http 相比,WebSocket 消息数据交换要轻得多,因此,在WebSocket客户端和WebSocket服务器进行频繁双向通信时,可以使服务器避免打开多个HTTP连接进行工作来节约资源,提高了工作效率和资源利用率。
  • 数据类型: WebSocket传输支持文本类型、二进制类型(图片、动画等),还可以传输自定义的消息类型。
  • 单个 TCP 连接 : 初始连接使用 HTTP,然后将此连接升级到基于套接字的连接。然后这个单一连接用于所有未来的通信。

在这里插入图片描述

二、WebSocket使用场景

HTTP 不适用于两个应用程序之间的长时间实时工通信,但是WebbSocket允许服务端主动向客户端推送数据,并且不用遵循一问一答的规则,具有良好的互动性和时效性。

1.消息推送

公告、新闻推送

2.实时聊天

对话框实时通信

3.弹幕

4.实时数据更新

股票报价、体育比赛分数刷新

三、SpringBoot整合WebSocket(以实现消息推送为例)

来源:spring官方网站给予使用websocket的demo:https://spring.io/guides/gs/messaging-stomp-websocket/

这个项目demo是官网给的示例demo,直接pull下来复制一下就完全可以用了,以下是我把示例demo集成到自己项目的过程:

1.添加依赖

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

2.创建消息类

就是你想要的消息是怎么样的,有哪些字段和值,例如我的消息类是这样设计的

{
	# 用户连接ID
	"clientId":"36人7829",
	# 消息编码:可进行自定义,例如001是消息通告,002是广告
	"messageCode":"001",
	# 消息内容
	"messageContent":"好消息,打折了",
}
package com.cloud.springnacos9001.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * @author caicai
 */
@Data
@AllArgsConstructor
public class WebSocketMessage {

    /**
     * 用户ID
     */
    private String clientId;

    /**
     * 消息编码:可进行自定义,例如001是消息通告,002是广告
     */
    private String messageCode;

    /**
     * 消息内容
     */
    private String messageContent;
}

2.WebSocket配置类

package com.cloud.springnacos9001.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * WebSocket配置类
 */
@Configuration
@EnableWebSocket
public class WebSocketConfig {

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

}

3.工具类

package com.cloud.springnacos9001.controller;

import com.cloud.springnacos9001.entity.WebSocketMessage;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;


/**
 *
 * @author caicai
 * @date
 * @ServerEndpoint
 */
@Component
@Slf4j
@ServerEndpoint(value = "/websocket")
public class WebSocketServer {
    /**
     * 某个客户端连接的session
     */
    private Session session;

    private static ConcurrentHashMap<String,Session> clientMap = new ConcurrentHashMap<>();

    /**
     * 建立连接后调用的方法
     * @param session
     */
    @OnOpen
    public void onOpen(Session session){
        log.info("-----websocket成功连接------");
        this.session = session;
        clientMap.put(this.session.getId(),this.session);
    }

    /**
     * 处理客户端失败连接
     */
    @OnClose
    public void onClose(){
        clientMap.remove(this.session.getId());
        log.info("客户端失去连接,其sessionID为:"+this.session.getId());
    }

    /**
     * 连接报错时的处理方式
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("消息发生错误:"+session.getId());
        error.printStackTrace();
    }

    /**
     * 如果需要服务器接受客户端的消息就在这里写了
     * @param text
     */
    @OnMessage
    public void onMessage(String text){
        log.info("接受到客户端传来的消息:"+text);
    }

    /**
     * 推送消息
     * getAsyncRemote获取异步端点(推荐使用这个)
     * getBasicRemote获取阻塞端点(不推荐,如果第一次发送失败,就会一直阻塞,影响后面的进行)
     * @param message
     */
    public static void sendMessage(WebSocketMessage message){
        // 遍历向所有用户发送消息
        clientMap.entrySet().stream().forEach(item ->{
            item.getValue().getAsyncRemote().sendText(message.getMessageContent());
        });
    }

    /**
     * 将消息发送给特定的用户
     */
    public static void sendToSpecClient(String clientId,WebSocketMessage webSocketMessage){
        if(clientMap.contains(clientId)){
            clientMap.get(clientId).getAsyncRemote().sendText(webSocketMessage.getMessageContent());
        }else{
            clientMap.remove(clientId);
            // throw new RuntimeException("特定用户消息发生错误,请稍后重试");
        }
    }


}

4.测试连接

用于测试ws的网站:http://www.jsons.cn/websocket/
本机联调的时候可以用
在这里插入图片描述

5.服务调用

 @PostMapping("message")
 public String sendWebSocketMessage(@Param("message") String message){
     String content = "向所有用户推送消息:"+message;
     WebSocketServer.sendMessage(new WebSocketMessage(null,"001",content));
     return "SUCCESS";
 }

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

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

相关文章

人工智能 :一种现代的方法 第七章 逻辑智能体

文章目录 前言人工智能 &#xff1a;一种现代的方法 第七章 逻辑智能体7.1 基于知识的智能体7.2 Wumpus世界7.4 命题逻辑7.5 命题逻辑定理证明7.5.1推导和证明7.5.2 归结原理7.5.3 horn子句和限定子句7.5.4 前向链接和后向链接 7.6 有效命题逻辑模型求解7.6.1完备的回溯算法7.6…

MySQL主从延时问题

过线上 MySQL 维护经验的童鞋都知道&#xff0c;主从延迟往往是一个让人头疼不已的问题。 不仅仅是其造成的潜在问题比较严重&#xff0c;而且主从延迟原因的定位尤其考量 DBA 的综合能力&#xff1a;既要熟悉复制的内部原理&#xff0c;又能解读主机层面的资源使用情况&#…

使用PHP编写采集药品官方数据的程序

目录 一、引言 二、程序设计和实现 1、确定采集目标 2、使用PHP的cURL库进行数据采集 3、解析JSON数据 4、数据处理和存储 5、数据验证和清理 6、数据输出和可视化 7、数据分析和挖掘 三、注意事项 1、合法性原则 2、准确性原则 3、完整性原则 4、隐私保护原则 …

如何在 Windows 10/11 上高质量地将 WAV 转换为 MP3

WAV 几乎完全准确地存储了录音硬件所听到的内容&#xff0c;这使得它变得很大并占用了更多的存储空间。因此&#xff0c;WAV 格式在作为电子邮件附件发送、保存在便携式音频播放器上、通过蓝牙或互联网从一台设备传输到另一台设备等时可能无法正常工作。 如果您遇到 WAV 问题&…

【Android Studio调试报错】setContentView(R.layout.activity_main);

报错如下&#xff1a; 解决方法&#xff1a; 1、把参数删除到只剩 .&#xff0c;用自动补齐的方式来查看当前文件的位置是不是&#xff0c;当前左侧工程中layout 所在的位置。在的话它会在自动补齐列表有选项。否则我们选中第一个。 2、选中之后是这样的 然后问题解决&#xf…

飞天使-url路由进阶应用

url 的name属性 为 app01的url设定命名空间 app_name app01urlpatterns [path(, views.index, nameindex),path(login/, views.login, namelogin), ] 上面的namelogin 同时 from django.shortcuts import render,reverse,redirect 便于项目引用 def index(request):userna…

spring cloud-注册中心(Eureka)

一、服务注册中心组件(*) 定义&#xff1a;服务注册中心就是在整个微服务架构单独抽取一个服务&#xff0c;该服务不做项目中任何业务功能&#xff0c;仅用来在微服务中记录微服务、对微服务进行健康状态检查&#xff0c;及服务元数据信息存储常用的注册中心&#xff1a;eurek…

用placement label代替keep margin解决绕线问题

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 通常我们用keepout margin去降低多pin cell类型的密度&#xff0c;这里提供一种替代方案&#xff0c;即使用placement label。好处是只限制多pin cell彼此间距&#xff0c;不会…

echarts官网卡?

全网echarts案例资源大总结和echarts的高效使用技巧&#xff08;细节版&#xff09; - 掘金 drawnLine() {let myChart echarts.init(document.getElementById("grade"));// 绘制图表myChart.setOption({title: {left: "center",},tooltip: {trigger: &qu…

2023.11.13 Spring Bean 的生命周期

目录 Spring 执行流程 Bean 的生命周期 五个阶段 深入理解 Bean 初始化 实例理解 总结梳理 经典面试题 Spring 执行流程 Bean 的生命周期 Spring 中 Bean 的生命周就是 Bean 在 Spring 中从创建到销毁的整个过程 五个阶段 1. 实例化 Bean 为 Bean 对象分配内存空间 …

千万富翁分享:消费多少免单多少,电商运营高手实战秘籍拆解

千万富翁分享&#xff1a;消费多少免单多少&#xff0c;电商运营高手实战秘籍拆解 后疫情时代&#xff0c;国内电商圈层进程依然是在高速发展阶段&#xff0c;今年2023年双十一也彻底落下帷幕&#xff0c;但这次相较于往常却没有公布具体的成交规模数据&#xff0c;那么&#x…

程序员,你的护城河挖好了吗?

程序员的护城河 在遥远的古代&#xff0c;护城河是一种防御工事&#xff0c;通常用于保护城市或城堡免受外部攻击。它是由人工挖掘或天然形成的河流、壕沟或城墙等&#xff0c;可以作为防御屏障&#xff0c;阻止敌人的进入。 而对于程序员而言&#xff0c;“护城河”是一种比喻…

Linux线程池

文章目录&#xff1a; 线程池了解线程池模拟实现 线程池了解 线程池是一种常见的线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待着监督管理者分配可并发执行的任务&#xff0c;以避免在处理短时间任…

Word或者WPS批量调整文中图片大小的快捷方法

文章目录 0、前言1、编写宏代码2、在文档中调用宏实现一键批量调整3、就这么简单&#xff01; 0、前言 不知道大家是不是也和我一样&#xff0c;经常需要在编写的Word&#xff08;或者WPS&#xff09;文档里插入大量的图片&#xff0c;但是这些图片的尺寸大小一般都不一样&…

2D 3D 工业组态技术 meta2d JavaScript

本心、输入输出、结果 文章目录 2D 3D 工业组态技术 meta2d JavaScript前言2D 3D 工业组态技术 meta2d JavaScript 简介2D 3D 工业组态技术 meta2d JavaScript 特性丰富的组态能力0代码数据通信组态的应用多端适配能力强大的扩展能力追求卓越性能丰富的组件库资源广泛的应用场景…

致刘家窑中医院龚洪海医生:患者的感谢与敬意

你们好!我曾经是咱们这的一名患者&#xff0c;我叫李刚&#xff0c;今年45岁&#xff0c;不知道你们还有印象吗?我曾去过一些医院进行就诊&#xff0c;但都没有得到恰当的治疗&#xff0c;症状一直没有消失。得了这个病之后对我的生活以及工作打击都十分的大。经朋友介绍说刘家…

【Linux系统编程十七】:(基础IO4)--文件系统(inode与软硬链接)

【Linux系统编程十六】&#xff1a;文件系统&#xff08;inode与软硬链接&#xff09; 一.磁盘硬件二.文件系统(inode)三.软硬链接 一.磁盘硬件 Linux下的文件在磁盘中存储&#xff0c;文件的内容和属性是分开存储的&#xff01; 文件的内容存储在数据块。 文件的属性存储在in…

专业的软件第三方检测机构如何做性能测试?收费标准是多少?

随着软件信息技术的飞速发展&#xff0c;人们对于软件产品越来越依赖&#xff0c;从而用户对软件产品的稳定性和质量问题愈发看重。软件系统性能的好坏将严重影响该软件的质量和软件开发者的利益&#xff0c;为了更好的保障软件产品质量&#xff0c;软件企业会将性能测试交由软…

python 爬虫之urllib 库的相关模块的介绍以及应用

文章目录 urllib.request 模块打开 URL&#xff1a;发送 HTTP 请求&#xff1a;处理响应&#xff1a; 应用如何读取并显示网页内容提交网页参数使用HTTP 代理访问页面 urllib.request 模块 在 Python 中&#xff0c;urllib.request 模块是用于处理 URL 请求的标准库模块之一。…

vscode删除后重装还有原来的配置问题,彻底删除vscode,删除vscode安装过的插件和缓存

VSCode卸载后进行重新安装&#xff0c;发现新安装的还有原来的一些配置&#xff0c;卸载的不彻底&#xff0c;有时候也容易出问题&#xff0c;可按照如下方法卸载干净&#xff1a; 1.进入控制面板卸载VSCode&#xff0c;也可以在VSCode的安装目录下用程序自带的卸载程序 2.这…