• websocket系列基于spring-boot-starter-websocket实现


    前言

    2021春节后第一篇文章,承接之前继续完成websocket系列,本篇主要是介绍怎么基于spring-boot-starter-websocket来实现websocket。


    一、项目结构

    在这里插入图片描述

    二、具体说明

    1.引入maven依赖

    
            
                org.springframework.boot
                spring-boot-starter-websocket
            
    
            
                org.springframework.boot
                spring-boot-starter-web
            
    
            
                org.projectlombok
                lombok
                true
            
            
                org.springframework.boot
                spring-boot-starter-test
                test
            
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2.实现WebSocketConfigurer配置类

    @Configuration
    @EnableWebSocket
    public class WebSocketConfig implements WebSocketConfigurer {
    
        @Autowired
        private MyWsHandler myWsHandler;
    
        @Override
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry
                    .addHandler(myWsHandler, "myWs")
                    //允许跨域
                    .setAllowedOrigins("*");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    说明:
    通过实现WebSocketConfigurer配置类,重写registerWebSocketHandlers方法,注册自定义的WebSocketHandler的实现类MyWsHandler,并指定类对应的websocket访问的ServerEndpoint为/myWs。
    通过@EnableWebSocket注解,启动spring-boot-starter-websocket的自动化配置。

    3.自定义WebSocketHandler

    /**
     * ws消息处理类
     */
    @Component
    @Slf4j
    public class MyWsHandler extends AbstractWebSocketHandler {
    
        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
            log.info("建立ws连接");
            WsSessionManager.add(session.getId(),session);
        }
    
        @Override
        protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
            log.info("发送文本消息");
            // 获得客户端传来的消息
            String payload = message.getPayload();
            log.info("server 接收到消息 " + payload);
            session.sendMessage(new TextMessage("server 发送给的消息 " + payload + ",发送时间:" + LocalDateTime.now().toString()));
        }
    
        @Override
        protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
            log.info("发送二进制消息");
        }
    
        @Override
        public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
            log.error("异常处理");
            WsSessionManager.removeAndClose(session.getId());
        }
    
        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
            log.info("关闭ws连接");
            WsSessionManager.removeAndClose(session.getId());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    说明:
    通过继承 AbstractWebSocketHandler 类并覆盖相应方法,可以对 websocket 的事件进行处理,这里可以同原生注解的那几个注解连起来看
    afterConnectionEstablished 方法是在 socket 连接成功后被触发,同原生注解里的 @OnOpen 功能。
    afterConnectionClosed方法是在 socket 连接关闭后被触发,同原生注解里的 @OnClose 功能。
    handleTextMessage方法是在客户端发送普通文件信息时触发,同原生注解里的 @OnMessage 功能。
    handleBinaryMessage 方法是在客户端发送二进制信息时触发,同原生注解里的 @OnMessage 功能。
    handleTransportError方法同原生注解里的@OnError。

    除了继承AbstractWebSocketHandler类外,还有以下WebSocketHandler可供选择。
    AbstractWebSocketHandler可以同时支持普通文本和二进制的消息处理。
    BinaryWebSocketHandler只支持二进制消息。
    TextWebSocketHandler只支持普通文本消息。
    在这里插入图片描述

    4.定时消息推送MessageJob

    /**
     * 消息生成job
     */
    @Slf4j
    @Component
    public class MessageJob {
        @Autowired
        WsService wsService;
    
        /**
         * 每5s发送
         */
        @Scheduled(cron = "0/5 * * * * *")
        public void run(){
            try {
                wsService.broadcastMsg("自动生成消息 "  + LocalDateTime.now().toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    5.消息推送服务类WsService

    /**
     * ws操作相关服务
     */
    @Service
    @Slf4j
    public class WsService {
    
        /**
         * 发送消息
         * @param session
         * @param text
         * @return
         * @throws IOException
         */
        public void sendMsg(WebSocketSession session, String text) throws IOException {
            session.sendMessage(new TextMessage(text));
        }
    
        /**
         * 广播消息
         * @param text
         * @return
         * @throws IOException
         */
        public void broadcastMsg(String text) throws IOException {
            for (WebSocketSession session: WsSessionManager.SESSION_POOL.values()) {
                session.sendMessage(new TextMessage(text));
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    6.Session管理类WsSessionManager

    @Slf4j
    public class WsSessionManager {
        /**
         * 保存连接 session 的地方
         */
        public  static ConcurrentHashMap SESSION_POOL = new ConcurrentHashMap<>();
    
        /**
         * 添加 session
         *
         * @param key
         */
        public static void add(String key, WebSocketSession session) {
            // 添加 session
            SESSION_POOL.put(key, session);
        }
    
        /**
         * 删除 session,会返回删除的 session
         *
         * @param key
         * @return
         */
        public static WebSocketSession remove(String key) {
            // 删除 session
            return SESSION_POOL.remove(key);
        }
    
        /**
         * 删除并同步关闭连接
         *
         * @param key
         */
        public static void removeAndClose(String key) {
            WebSocketSession session = remove(key);
            if (session != null) {
                try {
                    // 关闭连接
                    session.close();
                } catch (IOException e) {
                    // todo: 关闭出现异常处理
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 获得 session
         *
         * @param key
         * @return
         */
        public static WebSocketSession get(String key) {
            // 获得 session
            return SESSION_POOL.get(key);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    7.启动类SpringWsApplication

    @SpringBootApplication
    @EnableScheduling
    public class SpringWsApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringWsApplication.class, args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    8.首页index.html

    发现很多小伙伴不知道调用WebSocket的前端页面怎么写,这里重新补充一下。

    
    
    
        My WebSocket
    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    9.测试

    在这里插入图片描述


    总结

    基于spring-boot-starter-websocket实现也非常简单,主要是3个实现步骤:
    1.通过继承AbstractWebSocketHandler自定义WebSocketHandler,重写afterConnectionEstablished、handleTextMessage、handleBinaryMessage、handleTransportError、afterConnectionClosed等方法,都能和jdk的原生websocket注解对应上。
    2.通过实现WebSocketConfigurer进行WebSocket的相关配置,利用WebSocketHandlerRegistry注册自定义的WebSocketHandler。
    3.消息的发送主要是通过WebSocketSession来实现。

  • 相关阅读:
    el-table 翻页记住上页选项,包含回显选中的数据
    shell脚本 重试 分文件 多进程
    软件设计体系 实验一 经典软件体系结构风格
    Flutter Widget 如何启用和屏蔽点击事件
    Java-随机数据生成器(造数据)
    Chapter6视觉处理基础
    sqlserver 语句执行了多长时间
    shell脚本学习笔记02(小滴课堂)
    Mysql 表的约束
    Linux下du指令详情介绍
  • 原文地址:https://blog.csdn.net/web13618542420/article/details/126551816