首页 > 其他分享 >SpringBoot引入WebSocket

SpringBoot引入WebSocket

时间:2024-07-06 15:54:06浏览次数:17  
标签:websocket WebSocket SpringBoot session 引入 import message public

WebSocket 是一种在客户端和服务器之间提供低延迟、全双工通信的网络协议。它允许双方在建立一次连接后,进行实时、持续的数据交换,无需像HTTP那样为每一个请求和响应建立新的连接。WebSocket的设计初衷是解决传统HTTP协议在实时通信方面的不足,比如实现实时聊天、游戏、股票报价等需要高频率、连续数据更新的应用场景。

1 构建服务端

1.1 引入依赖

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

1.2 创建配置类

@Slf4j
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

1.3 创建服务端

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

@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocketTest {
    /**
     * 线程安全的无序的集合
     */
    private static final CopyOnWriteArraySet<Session> SESSIONS = new CopyOnWriteArraySet<>();

    /**
     * 存储在线连接数
     */
    private static final Map<String, Session> SESSION_POOL = new HashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
        try {
            SESSIONS.add(session);
            SESSION_POOL.put(userId, session);
            log.info("【WebSocket消息】有新的连接,总数为:" + SESSIONS.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClose
    public void onClose(Session session) {
        try {
            SESSIONS.remove(session);
            log.info("【WebSocket消息】连接断开,总数为:" + SESSIONS.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnMessage
    public void onMessage(String message) {
        log.info("【WebSocket消息】收到客户端消息:" + message);
        Session session = SESSION_POOL.get("123");
        if (session != null && session.isOpen()) {
            try {
                synchronized (session) {
                    log.info("【WebSocket消息】单点消息:" + message);
                    session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

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

    /**
     * 此为单点消息
     *
     * @param userId  用户编号
     * @param message 消息
     */
    public void sendOneMessage(String userId, String message) {
        Session session = SESSION_POOL.get(userId);
        if (session != null && session.isOpen()) {
            try {
                synchronized (session) {
                    log.info("【WebSocket消息】单点消息:" + message);
                    session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 此为单点消息(多人)
     *
     * @param userIds 用户编号列表
     * @param message 消息
     */
    public void sendMoreMessage(String[] userIds, String message) {
        for (String userId : userIds) {
            Session session = SESSION_POOL.get(userId);
            if (session != null && session.isOpen()) {
                try {
                    log.info("【WebSocket消息】单点消息:" + message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2 创建客户端

2.1 引入依赖

 <dependency>
	 <groupId>org.java-websocket</groupId>
	 <artifactId>Java-WebSocket</artifactId>
	 <version>1.5.3</version>
</dependency>

2.2 注入对象

在配置类中注入WebSocketClient

import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import java.net.URI;

@Slf4j
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    @Bean
    public WebSocketClient webSocketClient() {
        WebSocketClient wsc = null;
        try {
            wsc = new WebSocketClient(new URI("ws://127.0.0.1:2580/websocket/123")) {
                @Override
                public void onOpen(ServerHandshake serverHandshake) {
                    log.info("与服务端建立连接");
                }

                @Override
                public void onMessage(String s) {
                    log.info("收到服务端的消息:{}", s);
                }

                @Override
                public void onClose(int i, String s, boolean b) {
                    log.info("与服务端的连接断开 code:{} reason:{} {}", i, s, b);
                }

                @Override
                public void one rror(Exception e) {
                    log.info("连接报错");
                }
            };
            wsc.connect();
            return wsc;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wsc;
    }
}

2.3 测试

import org.java_websocket.client.WebSocketClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class TestController {

    @Resource
    WebSocketClient wsClient;

    @GetMapping("/send")
    public void test(String text){
        wsClient.send(text);
    }
}

2.4 结果

浏览器访问

http://localhost:2580/send?text=测试

结果

2024-07-06 15:38:28.586  INFO 25860 --- [nio-2580-exec-4] c.x.p.websocket.socket.WebSocketTest     : 【WebSocket消息】收到客户端消息:测试
2024-07-06 15:38:28.586  INFO 25860 --- [nio-2580-exec-4] c.x.p.websocket.socket.WebSocketTest     : 【WebSocket消息】单点消息:测试
2024-07-06 15:38:28.587  INFO 25860 --- [ctReadThread-31] c.x.p.websocket.config.WebSocketConfig   : 收到服务端的消息:测试

image

标签:websocket,WebSocket,SpringBoot,session,引入,import,message,public
From: https://www.cnblogs.com/eaglex3/p/18287319

相关文章

  • 【SpringBoot】SpringBoot自动装配原理
    在上一篇文章中,讲述了SpringBoot核心启动流程源码解析其中,主要是构造方法和run方法的处理,本篇接着准备上下文环境后续,讲述是如何将springboot是如何完成自动装配,主线其实就是什么时候完成对主类的加载,也即对SpringBootApplication类加载到IOC容器中什么时候完成对Spring......
  • SpringBoot如何集成和使用开源工作流引擎camunda
    使用camunda开源工作流引擎有:通过docker运行、使用springboot集成、部署camunda发行包、基于源代码编译运行等多种方式。其中,通过源代码编译运行的方式最为复杂,具体参考:https://lowcode.blog.csdn.net/article/details/136206057文本重点介绍如何在SpringBoot应用程序中如何集......
  • 基于SpringBoot+vue的车辆充电桩系统(带1w+文档)
    基于SpringBoot+vue的车辆充电桩系统(带1w+文档)本次设计任务是要设计一个车辆充电桩管理系统,通过这个系统能够满足车辆充电桩管理系统的管理功能。系统的主要功能包括首页、个人中心、维修员管理、用户管理、电桩类别管理、充电桩管理、充电桩报修管理、维修回复管理、系......
  • 基于java+springboot+vue实现的图书商城管理系统(文末源码+Lw)283
     摘 要现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本图书商城管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理......
  • 基于java+springboot+vue实现的旅游推荐系统(文末源码+Lw)280
    摘 要传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装旅游推荐系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,旅游推荐系统的有效......
  • 基于java+springboot+vue实现的流浪动物管理系统(文末源码+Lw)277
     摘    要在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之前的纸张记录模式已经不符合当前使用要求了。所以,对流浪动物信息管理的提升,也为了对流浪动物信息进行更好的维护,流浪动物管理系统的出现就变得水到渠成......
  • 基于java+springboot+vue实现的药店管理系统(文末源码+Lw)285
    摘   要传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,药品信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广大用户的需求,因此就应运而生出相应的药店管理系统。本药店......
  • 基于java+springboot+vue实现的药店管理系统(文末源码+Lw)285
    摘   要传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,药品信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广大用户的需求,因此就应运而生出相应的药店管理系统。本药店......
  • 玩转springboot之springboot定制化tomcat
    定制化tomcatspringboot中是集成了tomcat容器的,如何定制化内置的tomcat呢?springboot提供了定制化的接口1.5.x版本在1.5.x版本中使用的是EmbeddedServletContainerCustomizer接口来进行定制化的public class MyTomcatCustomizer implements EmbeddedServletContaine......
  • 使用WebSocket和C语言实现一个简单的计算器
    在现代Web开发中,WebSocket已经成为实时通信的重要工具。本文将介绍如何使用WebSocket与C语言结合,实现一个简单的计算器应用。我们将通过Go语言作为中间层,调用C语言编写的计算函数,并通过WebSocket与前端进行交互。在使用本文章代码开发过程中遇到问题,可参考博主的另外两篇博客......