SpringBoot集成websocket作为客户端和服务端的代码案例

本文介绍了如何在SpringBoot项目中集成WebSocket,实现服务器主动向客户端推送数据,以及作为服务端和客户端的代码实现步骤。涵盖了WebSocket的基本概念、使用场景以及在前后端分离项目中的具体操作。
摘要由CSDN通过智能技术生成

websocket介绍:

WebSocket是一种在单个TCP连接上进行全双工通信的协议,允许服务端和客户端之间进行实时、双向的数据传输。

  • 长连接:WebSocket建立连接后,只要不关闭,会一直保持连接状态,使得服务器可以主动向客户端推送数据。
  • 双向通信:与HTTP请求-响应模式不同,WebSocket支持双向通信,即客户端和服务端都可以发送或接收数据。

使用场景:

在需要实时交互的场景中使用,例如聊天应用,实时数据推送,内容流式输出等。可实现实时向客户端进行数据推送。

1、SpringBoot集成websocket作为服务端

在前后端分离的项目中,前端作为websocket的客户端,后端服务作为websocket的服务端。

实现步骤:

  1. 添加websocket整合包

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    
  2. 编写websocket配置类,暴露WebSocket

    @Configuration
    public class WebSocketConfig {
    
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    
    }
    
  3. 编写websocket服务监听程序及处理逻辑

    package com.houdehong.wsserver.controller;
    
    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.io.IOException;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * @Author houdehong
     * @Date 2024/3/21 14:16
     * @Description
     **/
    @Component
    @ServerEndpoint("/api/ws/{sid}")
    @Slf4j
    public class WebSocketServer {
    
        private String sid;
    
        private static final ConcurrentHashMap<String, Session> SESSION_MAP = new ConcurrentHashMap<>();
    
        /**
         * 连接成功
         */
        @OnOpen
        public void onOpen(Session session, @PathParam("sid") String sid) {
            this.sid = sid;
            SESSION_MAP.put(sid, session);
            log.info("有新连接:sid:{},sessionId:{},当前连接数:{}", sid, session.getId(), SESSION_MAP.size());
        }
    
        /**
         * 连接关闭
         */
        @OnClose
        public void onClose(Session session) {
            SESSION_MAP.remove(this.sid);
            log.info("连接关闭,sid:{},session id:{}!当前连接数:{}", this.sid, session.getId(), SESSION_MAP.size());
        }
    
        /**
         * 收到消息
         */
        @OnMessage
        public void onMessage(String message, Session session) {
            log.info("收到消息:{},内容:{}", sid, message);
            if("ping".equals(message)){
                try {
                    session.getBasicRemote().sendText("pong");
                } catch (IOException e) {
                    log.error("onMessage 推送消息失败:{},内容:{}", sid, message);
                }
            }else{
                // 排除自己
               // sendMeasureDataInfoExcludeSelf(message, sid);
                // 发给所有客户端包括自己
                sendMeasureDataInfo(message);
            }
        }
    
    
        /**
         * 连接错误
         */
        @OnError
        public void onError(Session session, Throwable error) {
            log.error("{} 发生错误", session.getId(), error);
        }
    
        /**
         * 群发消息
         */
        public void sendMeasureDataInfo(String message) {
            for (String sid : SESSION_MAP.keySet()) {
                Session session = SESSION_MAP.get(sid);
                try {
                    session.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    log.error("推送消息失败:{},内容:{}", sid, message);
                }
                log.info("推送消息:{},内容:{}", sid, message);
            }
        }
    
        /**
         * 群发消息,排除消息发起者
         * @param message
         * @param sidSelf
         */
        private void sendMeasureDataInfoExcludeSelf(String message, String sidSelf){
            for(String sid : SESSION_MAP.keySet()){
                if(sidSelf.equals(sid)){
                    continue;
                }
                Session session = SESSION_MAP.get(sid);
                try {
                    session.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    log.error("sendMeasureDataInfoExcludeSelf 推送消息失败:{},内容:{}", sid, message);
                }
                log.info("sendMeasureDataInfoExcludeSelf 推送消息:{},内容:{}", sid, message);
            }
        }
    }
    
    
  4. 测试

    至此,springboot整合websocket作为服务就搭建完成了,我们可以随便百度打开一个在线的websocket测试工具,请求一下试试,请求地址是ws://ip:port/api/ws/{sid}, 其中sid可以随便指定一个字符串,这里的sid主要是用来区分客户端,实际场景下可以在前端生成全局唯一的标识。

    图片:
    在这里插入图片描述控制台打印信息:
    在这里插入图片描述

2、SpringBoot集成websocket作为客户端

有时,我们需要调用第三方的websocket服务,然后将接收到的数据处理之后,或持久化到数据库,或是需要解析数据重新封装为前端需要的数据结构,这个时候我们就需要作为客户端来进行使用。

实现步骤:

  1. 添加springboot服务作为客户端的依赖

    <dependency>
        <groupId>org.java-websocket</groupId>
        <artifactId>Java-WebSocket</artifactId>
        <version>1.3.8</version>
    </dependency>
    
  2. 继承WebSocketClient,重写方法,加入自己的逻辑

    @Slf4j
    public class MyWebSocketClient extends WebSocketClient {
    
        public MyWebSocketClient(URI serverUri) {
            super(serverUri);
        }
    
        @Override
        public void onOpen(ServerHandshake arg0) {
            log.info("------ WebSocketClient onOpen ------");
        }
    
        @Override
        public void onClose(int arg0, String arg1, boolean arg2) {
            log.info("------ WebSocket onClose ------{}",arg1);
        }
    
        @Override
        public void onError(Exception arg0) {
            log.error("------ WebSocket onError ------{}",arg0);
        }
    
        @Override
        public void onMessage(String response) {
            log.info("-------- 接收到服务端数据: " + response + "--------");
        }
    
    }
    
  3. 获取websocketClient实例

    在这里我写的wsServerUrl即为上面websocket作为服务端的地址

    @Component
    public class WebSocketClientConfigurer {
    
        private final String wsServerUrl = "ws://127.0.0.1:8081/api/ws/123wer";
    
        @Bean
        public WebSocketClient webSocketClient() {
            try {
                MyWebSocketClient webSocketClient =
                        new MyWebSocketClient(new URI(wsServerUrl));
                webSocketClient.connect();
                return webSocketClient;
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    }
    
  4. 为了好演示我加了一个controller来进行调用

    @RestController
    @RequestMapping("ws-client")
    public class WebsocketClient {
    
        @Resource
        private MyWebSocketClient webSocketClient;
    
        @GetMapping("send/{message}")
        public void sendRequest(@PathVariable String message){
            webSocketClient.send(message);
        }
    }
    

3. 测试

至此,我们已经搭好了一个websocket的服务器和一个websocket的客户端,我们可以同时把这两个服务跑起来,做一个调用。
注意:需要先启动服务端,再启动客户端,客户端会无法创建连接,报空指针异常。
服务端启动:
在这里插入图片描述客户端启动:
在这里插入图片描述现在我们向客户端的controller请求一个消息:
你可以用postman或者其他api工具,我现在图简单直接在浏览器发起:

在这里插入图片描述客户端控制台日志:

在这里插入图片描述服务端控制台日志:
在这里插入图片描述OK,大功告成。
整套源码包地址

  • 30
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot集成WebSocket客户端,你可以按照以下步骤进行操作: 1. 引入依赖:在你的项目的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 创建WebSocket配置类:创建一个WebSocketConfig类,用于配置WebSocket相关的bean。可以按照以下示例进行配置: ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myWebSocketHandler(), "/websocket-url").setAllowedOrigins("*"); } @Bean public WebSocketHandler myWebSocketHandler() { return new MyWebSocketHandler(); } } ``` 在上述示例中,我们定义了一个名为`myWebSocketHandler`的WebSocket处理程序,并将其映射到`/websocket-url`路径。你可以根据自己的需求进行修改。 3. 创建WebSocket处理程序:实现WebSocketHandler接口,创建一个自定义的WebSocket处理程序。例如: ```java public class MyWebSocketHandler extends TextWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 处理接收到的消息 String payload = message.getPayload(); // ... } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // 连接建立后的处理逻辑 // ... } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { // 连接关闭后的处理逻辑 // ... } } ``` 4. 发起WebSocket连接:在需要使用WebSocket的地方,注入`WebSocketClient`并使用它创建WebSocket连接。例如: ```java @Autowired private WebSocketClient webSocketClient; public void connectToWebSocket() { webSocketClient.doHandshake(new MyWebSocketHandler(), "ws://websocket-server-url"); } ``` 在上述示例中,我们使用`webSocketClient`发起WebSocket连接,并指定了WebSocket服务器的URL。 通过以上步骤,你就可以在Spring Boot集成WebSocket客户端了。你可以根据自己的需求,进一步扩展和定制WebSocket处理程序和配置类。希望对你有所帮助!如果你有更多问题,可以继续问我。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值