首页 > 其他分享 >Springboot实现WebSocket

Springboot实现WebSocket

时间:2023-06-20 18:32:38浏览次数:33  
标签:WebSocket Springboot 实现 userId session import websocket message public

一、什么是webSocket

WebSocket是HTML5下一种新的协议(Websocket协议本质上是一个基于tcp的协议),它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的,WebSocket是一个持久化的协议。

二、修改配置文件

在application.properties,修改内容为:

server.port = 8081
server.servlet.context-path= /api

三、修改pom.xml,下载对应的依赖

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>
        
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
  </dependency>
  <!--工具类 -->
	<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.4.1</version>
	</dependency>


四、新建两个类

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

@Configuration
public class WebSocketConfig {

    /**
     * 	注入ServerEndpointExporter,
     * 	这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

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

/**
 * 接口路径 ws://localhost:8087/webSocket/userId;
 */
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {

    /**
     *  与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    private Session session;

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

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    //虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。
    //  注:底下WebSocket是当前类名
    private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();

    // 用来存在线连接用户信息
    private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<String, Session>();

    /**
     * 链接成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
        try {
            this.session = session;
            this.userId = userId;
            webSockets.add(this);
            sessionPool.put(userId, session);
            log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());

            sendOneMessage(userId, "Hi,"+userId+",连接成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        try {
            webSockets.remove(this);
            sessionPool.remove(this.userId);
            log.info("【websocket消息】连接断开,总数为:" + webSockets.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("【websocket消息】收到客户端消息:" + message);
        if (StrUtil.isNotEmpty(this.userId)) {
            sendOneMessage(this.userId, "hi:" + userId + ",您发的信息:" + message);
        }
    }

    /**
     * 发送错误时的处理
     *
     * @param session
     * @param error
     */
    @OnError
    public void one rror(Session session, Throwable error) {

        log.error("用户错误,原因:" + error.getMessage());
        error.printStackTrace();
    }


    // 此为广播消息
    public void sendAllMessage(String message) {
        log.info("【websocket消息】广播消息:" + message);
        for (WebSocket webSocket : webSockets) {
            try {
                if (webSocket.session.isOpen()) {
                    webSocket.session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息
    public void sendOneMessage(String userId, String message) {
        Session session = sessionPool.get(userId);
        if (session != null && session.isOpen()) {
            try {
                log.info("【websocket消息】 单点消息:" + message);
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息(多人)
    public void sendMoreMessage(String[] userIds, String message) {
        for (String userId : userIds) {
            Session session = sessionPool.get(userId);
            if (session != null && session.isOpen()) {
                try {
                    log.info("【websocket消息】 单点消息:" + message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

五、测试功能

Springboot实现WebSocket_websocket

效果如下:

Springboot实现WebSocket_springboot_02

Springboot实现WebSocket_springboot_03

标签:WebSocket,Springboot,实现,userId,session,import,websocket,message,public
From: https://blog.51cto.com/u_11315052/6524281

相关文章

  • 基于PHP理工大社区管理系统的设计与实现
    随着信息技术的飞速发展,特别是网络和数据库技术的发展,计算机已经成为当今处理信息数据的主要工具。数据库技术已经成为计算机应用技术中的一个重要组成部分,对于大量的数据,使用数据库来存储管理会比文件来存储数据,管理起来更高效、方便。人们对于现实中的各种事物的管理,已经越来越依......
  • 5步带你玩转SpringBoot自定义自动配置那些知识点
    目前SpringBoot框架真的深受广大开发者喜爱,毕竟它最大的特点就是:快速构建基于Spring的应用程序的框架,而且它提供了各种默认的功能和配置,可以让开发者快速搭建应用程序的基础结构。但是,当我们需要自定义一些配置时,我们就需要使用自定义自动配置。今天一定让大家深刻体验干货知识点......
  • 插入排序及C语言实现
    一、插入排序原理插入排序是一种简单的排序算法,其基本思想是将未排序序列中的每个元素依次插入到已排序的序列中合适的位置。具体来说,假设待排序的序列为a1,a2,⋯,an,则从a2开始遍历整个序列,将ai插入到前面的已排序序列a1,⋯,ai−1中,直到所有的元素都被插入到已排序的序列中......
  • C 语言 GCC 内嵌函数实现 Lambda 表达式
    代码({//函数实现函数名称;})#include<stdio.h>#include<malloc.h>#defineaction_lambda(function_body)\({voidlambda_funcfunction_bodylambda_func;})#definefunc_lambda(return_type,function_body)\({return_typelambda_funcfunction_b......
  • springboot+websocket简单使用
    一、引入依赖<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.o......
  • springboot简易配置
    server:port:8089servlet:encoding:charset:UTF-8tomcat:uri-encoding:UTF-8spring:datasource:type:com.zaxxer.hikari.HikariDataSourcejdbc-url:jdbc:mysql://localhost:3306/mydb_base?serverTimezone=UTC&useUnicode=t......
  • TwinCAT3 - 实现自己的Tc2_SerialCom
    目录1,前言2,原生Tc2_SerialCom简单使用3,实现自己的Tc2_SerialCom3.1,EL6inData22B,EL6outData22B3.2,ComBuffer3.3,SerialLineControl3.4,SendString,ReceiveString4,自己的Tc2_SerialCom简单使用5,总结1,前言在TwinCAT3中,典型的串口通信,硬件需要模块EL6022(类似的模块有EL6001、EL6002、E......
  • 批量打印文件doc,设置几分,powershell实现
    $folderPath="C:\path\to\folder"$printCopies=3Get-ChildItem-Path$folderPath-Filter*.doc|ForEach-Object{for($i=0;$i-lt$printCopies;$i++){Start-Process-FilePath$_.FullName-VerbPrint}}#一定要指定默认打印机......
  • 浅谈项目核算的“全程利润”实现模式
    “怎样评估各事业群/项目群的业绩?如何引导决策?”“今年的利润怎么分配?没有细化的分配依据,怎么办?”“开了这么多类型的项目,是不是有些盲目?资源这么紧张,明年要怎么做?”这一系列的问题,几乎所有的企业都会面临,怎么破?怎么解?用友针对以上困惑推出了一项新的解决方案“项目财务管理PFM”,将......
  • SpringBoot整合Cache缓存深入理解
    我们在上一篇的基础上继续学习。SpringBoot整合cache缓存入门一、@Caching注解@Caching注解用于在方法或者类上,同时指定多个Cache相关的注解。属性名描述cacheable用于指定@Cacheable注解put用于指定@CachePut注解evict用于指定@CacheEvict注解示例代码如下:importcom.example.mys......