SpringBoot--05--整合WebSocket,实现全双工通信

news2024/11/14 12:22:08

文章目录

      • 为什么需要websocket
      • 项目中使用websocket
        • 导入maven坐标
        • 编写配置类
        • server代码
        • 前端代码
        • 和http请求URL区别

为什么需要websocket

传统的HTTP协议是单向通信的,支持客户端向服务器发送请求,服务器接收请求。但是服务器有时也要向客户端发送请求。

websocket是一个全双工的通信协议,客户端可以向服务器发送请求,服务器也可以向客户端发送请求。

应用场景:订单通知、弹幕系统、比赛或者直播一些实时的排行榜数据。

网上定义:
WebSocket 是一种基于 TCP 协议的全双工通信协议,它允许客户端和服务器之间建立持久的、双向的通信连接。相比传统的 HTTP 请求 - 响应模式,WebSocket 提供了实时、低延迟的数据传输能力。通过 WebSocket,客户端和服务器可以在任意时间点互相发送消息,实现实时更新和即时通信的功能。WebSocket 协议经过了多个浏览器和服务器的支持,成为了现代 Web 应用中常用的通信协议之一。它广泛应用于**聊天应用、实时数据更新、多人游戏等场景,**为 Web 应用提供了更好的用户体验和更高效的数据传输方式。

项目中使用websocket

导入maven坐标
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
编写配置类

编写配置类,用户注册websocket的bean

@Configuration
public class WebSocketConfiguration {

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

}
server代码

编写server代码
@ServerEndpoint(“/ws/{sid}”) 类似于RequestMapping。
接收前端传过来的参数。

package com.njitzx.controller;

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.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket服务
 */
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {

    //存放会话对象   存放会话对象
    private static Map<String, Session> sessionMap = new HashMap();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        System.out.println("客户端:" + sid + "建立连接");
        sessionMap.put(sid, session);
    }

    /**
     * 收到客户端消息后调用的方法   类似于Controller的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到来自客户端:" + sid + "的信息:" + message);
    }

    /**
     * 连接关闭调用的方法
     *
     * @param sid
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("连接断开:" + sid);
        sessionMap.remove(sid);
    }

    /**
     * 群发
     *
     * @param message
     */
    public void sendToAllClient(String message) {
        //将前端传过来的数据群发, 所有人都能拿到会话   values拿到map集合的所有属性值
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //服务器向客户端发送消息
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

使用定时任务向前端发送消息。

import com.njitzx.controller.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Component
public class WebSocketTask {
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 通过WebSocket每隔5秒向客户端发送消息
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void sendMessageToClient() {
        webSocketServer.sendToAllClient("这是来自服务端的消息 外卖超时了老哥:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
    }
}

需要在启动类上面加上注解,开启定时器

//开始定时器
@EnableScheduling
前端代码
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>WebSocket Demo</title>
</head>
<body>
    <input id="text" type="text" />
    <button onclick="send()">发送消息</button>
    <button onclick="closeWebSocket()">关闭连接</button>
    <div id="message">
    </div>
</body>
<script type="text/javascript">
    var websocket = null;
    var clientId = Math.random().toString(36).substr(2);

    //判断当前浏览器是否支持WebSocket
    if('WebSocket' in window){
        //连接WebSocket节点
        websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);
    }
    else{
        alert('Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function(){
        setMessageInnerHTML("error");
    };

    //连接成功建立的回调方法
    websocket.onopen = function(){
        setMessageInnerHTML("连接成功");
    }

    //接收到消息的回调方法
    websocket.onmessage = function(event){
        setMessageInnerHTML(event.data);
    }

    //连接关闭的回调方法
    websocket.onclose = function(){
        setMessageInnerHTML("close");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function(){
        websocket.close();
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML){
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //发送消息
    function send(){
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
	
	//关闭连接
    function closeWebSocket() {
        websocket.close();
    }
</script>
</html>
和http请求URL区别

前端发送的请求参数格式,正常是http开头的,websocket请求是ws开头的
在这里插入图片描述

最后用ChatGPT生成了理解配置项

`ServerEndpointExporter` 是 Spring 框架中用于配置 WebSocket 端点的一个类,特别是在 Spring WebSocket 支持中。它位于 `org.springframework.web.socket.server.standard` 包中。

### `ServerEndpointExporter` 的关键点:

1. **作用**- `ServerEndpointExporter` 的主要作用是注册通过 `@ServerEndpoint` 注解定义的 WebSocket 端点。
   - 它会扫描应用上下文中的所有带有 `@ServerEndpoint` 注解的 bean,并将它们注册到底层的 WebSocket 服务器中。

2. **使用场景**- 通常,你需要在 Spring 配置类中声明一个 `ServerEndpointExporter` bean。如果你使用 `@ServerEndpoint` 注解来定义 WebSocket 端点,那么这个 bean 是必须的。
   - 但如果你将应用部署到外部的 servlet 容器(如 Tomcat、Jetty 或 Undertow),通常不需要 `ServerEndpointExporter`,因为这些容器会自动处理 WebSocket 端点的注册。

3. **配置示例**:
   ```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();
       }
   }
  • 在这个配置中,serverEndpointExporter 方法返回一个 ServerEndpointExporter bean,允许自动注册 WebSocket 端点。
  1. 重要说明
    • 如果你的 Spring Boot 应用程序打包为 WAR 文件并部署到外部 servlet 容器中,不应包含 ServerEndpointExporter,因为这可能会与容器的 WebSocket 配置产生冲突。
    • 对于打包为独立 JAR 文件(使用嵌入式 servlet 容器如 Tomcat)的应用,ServerEndpointExporter 是支持 WebSocket 所必需的。
      ServerEndpointExporter 是 Spring 中用于自动注册带有 @ServerEndpoint 注解的 WebSocket 端点的工具类。在使用嵌入式 servlet 容器的独立 Spring Boot 应用中,它是必需的,但在部署到外部 servlet 容器时通常不需要它。

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

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

相关文章

万能视频播放器PotPlayer

软件介绍 PotPlayer播放器是一款全能 多媒体 影音播放器,堪称Windows平台最强大的本地 视频播放器. PotPlayer最新版拥有强劲播放引擎加速,支持DXVA,CUDA,QuickSync,多媒体播放器支持蓝光3D,其内置强大的编码器及滤镜/分离器。 支持自定义添加解码器,对字幕的支持非常优秀,能…

基于CST的特征模天线设计

前言&#xff1a; 特征模理论是在矩量法基础上发展而来的适用于各种电磁辐射和散射问题分析的理论&#xff0c;它有效综合了这两类方法的长处且克服了它们的不足&#xff0c;不仅可以通过明确的物理含义来直观深刻地揭示天线的工作原理&#xff0c;而且能求解任意辐射结构的复…

谷粒商城实战笔记-193~194-商城业务-多线程-线程池

文章目录 一&#xff0c;193-商城业务-异步-异步复习1. 继承Thread类2. 实现Runnable接口3. 实现Callable接口结合FutureTask4. 使用线程池 二&#xff0c;194-商城业务-异步-线程池详解1&#xff0c;线程池七大参数2&#xff0c;面试题3&#xff0c;Executors能创建的4中线程池…

个人经历分享如何用Python日入1K+,分享兼职网站和渠道!

大部分人主要通过接私活赚钱。我第一次接单是朋友介绍的&#xff0c;当时刚学Python&#xff0c;为一家公司爬数据&#xff0c;赚了一千多。从那之后逐渐熟练&#xff0c;常在假期接一些数据处理的单&#xff0c;很多时候兼职收入是主业收入的2~3倍。 附上我前两年的兼职接单记…

黑马头条vue2.0项目实战(十一)——功能优化(组件缓存、响应拦截器、路由跳转与权限管理)

1. 组件缓存 1.1 介绍 先来看一个问题&#xff1f; 从首页切换到我的&#xff0c;再从我的回到首页&#xff0c;我们发现首页重新渲染原来的状态没有了。 首先&#xff0c;这是正常的状态&#xff0c;并非问题&#xff0c;路由在切换的时候会销毁切出去的页面组件&#xff…

【vue讲解:vue3介绍、setup、ref、reactive、监听属性、生命周期、toRef、setup写法】

1 vue3介绍 # Vue3的变化-vue3完全兼容vue2---》但是vue3不建议用vue2的写法-拥抱TypeScript-之前咱们用的JavaScript---》ts完全兼容js- 组合式API和配置项APIvue2 是配置项apivue3 组合式api# vue4必须要用2 vue3项目创建和启动 # 创建vue3项目-vue-cli 官方不太建议用了…

【Java学习】方法的引用

所属专栏&#xff1a;Java学习 &#x1f341;1. 方法引用 方法的引用&#xff1a;把已经存在的方法拿来使用&#xff0c;当作函数式接口中抽象方法的方法体 " :: "是方法引用符 方法引用时需要注意&#xff1a; 1. 需要有函数式接口 2. 被引用的方法必须存在 3. …

4款专业高效的Win10 录屏工具大揭秘!

Win10 系统里面一般都有自带的录屏工具&#xff0c;用截图工具就可以实现录屏。但是呢&#xff0c;这个工具只适合录制一些简短的小片段。如果想要更多功能的录屏&#xff0c;还是需要使用到第三方的录屏工具&#xff0c;这次&#xff0c;我就跟大家分享4款专业的录屏软件。 1、…

拟南芥中基因家族序列的提取

1.拟南芥基因组数据的下载 phytozome 是一个收录植物基因组数据的网站&#xff0c;数据整理比较规范&#xff0c;已 经提供了去除可变剪切的 cds 和 protein 序列文件。只有 gff3 文件需要 过滤处理 2. 对拟南芥的注释文件gff3文件进行ID处理&#xff0c;最终得到以下4个文件 …

深度解析:.secret勒索病毒如何加密你的数据并勒索赎金

引言&#xff1a; 在当今这个数字化、信息化的时代&#xff0c;网络安全已成为一个不容忽视的重要议题。随着互联网的普及和技术的飞速发展&#xff0c;我们的生活、工作乃至整个社会的运转都越来越依赖于各种计算机系统和网络。然而&#xff0c;这种高度依赖也为我们带来了前…

硬件面试经典 100 题(51~70 题)

51、请列举您知道的覆铜板厂家。 生益、建滔。 52、示波器铭牌一般都会标识两个参数&#xff0c;比如泰克 TDS1002B 示波器标识的 60MHz 和 1GS/s&#xff0c;请解释这两个参数的含义。 60MHz 是指示波器的带宽&#xff0c;即正常可以测量 60MHz 频率以下的信号。 1GS/s 是指示…

鲲鹏920s 32核处理器linpack性能调优

1、BIOS参数调优 BIOS选项 设置值 Power Policy Performance Stream Write Mode Allocate share LLC CPU Prefetching Configuration Enabled Custom Refresh Rate 64ms Die Interleaving Disabled NUMA Enable SSBS Support Disabled 2、benchmark参数调优 主…

vue项目将px转成其他单位,如rem、cqw,postcss-pxtorem的使用

安装插件 新建配置文件.postcssrc.js // module.exports { // "plugins": { // "postcss-pxtorem": { // rootValue: 1,//必须和rem的初始值一致 // propList: [*], // // selectorBlackList: [ // // ant…

计算函数(c语言)

1.描述 //小乐乐学会了自定义函数&#xff0c;BoBo老师给他出了个问题&#xff0c;根据以下公式计算m的值。 // //其中 max3函数为计算三个数的最大值&#xff0c;如&#xff1a; max3(1, 2, 3) 返回结果为3。 //输入描述&#xff1a; //一行&#xff0c;输入三个整数&#xff…

3的幂计算

给定一个整数&#xff0c;写一个函数来判断它是否是 3 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 整数 n 是 3 的幂次方需满足&#xff1a;存在整数 x 使得 n 3x。 示例 1&#xff1a; 输入&#xff1a;n 27 输出&#xff1a;tru…

SpringCloud天机学堂:学习计划与进度(四)

SpringCloud天机学堂&#xff1a;学习计划与进度&#xff08;四&#xff09; 文章目录 SpringCloud天机学堂&#xff1a;学习计划与进度&#xff08;四&#xff09;1、业务接口统计2、实现接口2.1、查询学习记录2.2、提交学习记录2.3、创建学习计划2.4、查询学习计划进度 1、业…

从零掌握keepalived合集

文章目录 keepalived简介keepalived部署keepalived基础设置主配置文件修改独立子配置文件实现实现日志分离 企业应用实例抢占式与非抢占式抢占式非抢占式 VIP单波配置消息通知脚本配置 实现IPVS高可用keepalivedlvs实现keepaliveshaproxy实现 keepalived简介 keepalived基于VR…

GAMES104:07游戏中渲染管线、后处理和其他的一切-学习笔记

文章目录 前言一&#xff0c;Ambient Occlusion环境光遮蔽1.1 Precomputed AO1.2 Screen Space Ambient Occlusion(SSAO)1.3 Horizon-based Ambient Occlusion(HBAO)1.4 Ground Truth-based Ambient Occlusion(GTAO)1.5 Rat-Tracing Ambient Occlusion 二&#xff0c;雾效2.1 D…

Java MessagePack序列化工具(适配Unity)

Java MessagePack序列化工具&#xff08;适配Unity&#xff09; 前言项目代码编写 结 前言 前后端统一用MessagePack&#xff0c;结果序列化的结果不一样&#xff0c;发现C#侧需要给每个类增加描述字段数量的Head&#xff0c;而Java却不用&#xff0c;所以在Java侧封装一下序列…

51系列LY-51S出现下载失败·的解法

1.他的下载电路是特殊设计的 一般连接1&#xff0c;2&#xff0c;另外的接口2&#xff0c;3一般不接&#xff0c;而且2&#xff0c;3的功能是用来diy自动下载电路的&#xff0c;你接上2&#xff0c;3又没独特的下载电路会一直复位