• SpringBoot 整合 webSocket


    1、引入依赖:

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

    2、thymeleaf 配置:

    thymeleaf:
        encoding: UTF-8
        # 默认路径
        prefix: classpath:/templates/
        # 后缀
        suffix: .html
        # 模板的模式,支持 HTML, XML TEXT JAVASCRIPT
        mode: HTML5
        # 开发配置为false,避免修改模板还要重启服务器
        cache: false

    3、相关配置类:

    /**
     * 开启 webSocket 支持
     */
    @Configuration
    public class WebSocketConfig {
    
        @Bean
        public ServerEndpointExporter serverEndpointExporter () {
            return new ServerEndpointExporter();
        }
    }
    @ServerEndpoint(value = "/ws/asset")
    @Component
    public class WebSocketServer {
    
        @PostConstruct
        public void init() {
            System.out.println("WebSocket 加载");
        }
        private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
        private static final AtomicInteger OnlineCount = new AtomicInteger(0);
        // concurrent包的线程安全Set,用来存放每个客户端对应的Session对象。
        private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();
    
    
        /**
         * 客户端连接建立成功调用的方法
         * @param session
         */
        @OnOpen
        public void onOpen(Session session) {
            SessionSet.add(session);
            int cnt = OnlineCount.incrementAndGet(); // 在线数加1
            log.info("有连接加入,当前连接数为:{}", cnt);
            sendMessage(session, "连接成功");
        }
    
        /**
         * 客户端连接关闭调用的方法
         * @param session
         */
        @OnClose
        public void onClose(Session session) {
            SessionSet.remove(session);
            int cnt = OnlineCount.decrementAndGet();
            log.info("有连接关闭,当前连接数为:{}", cnt);
        }
    
        /**
         * 收到客户端消息后调用的方法
         * @param message   客户端发送过来的消息
         * @param session
         */
        @OnMessage
        public void onMessage(String message, Session session) {
            log.info("来自客户端的消息:{}",message);
            sendMessage(session, "收到消息,消息内容:"+ message);
    
        }
    
        /**
         * 出现错误
         * @param session
         * @param error
         */
        @OnError
        public void onError(Session session, Throwable error) {
            log.error("发生错误:{},Session ID: {}",error.getMessage(),session.getId());
            error.printStackTrace();
        }
    
        /**
         * 服务端推送消息(每次浏览器刷新,session会发生变化)
         * @param session
         * @param message
         */
        public static void sendMessage(Session session, String message) {
            try {
                session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId()));
            } catch (IOException e) {
                log.error("发送消息出错:{}", e.getMessage());
                e.printStackTrace();
            }
        }
    
        /**
         * 服务端群发消息
         * @param message
         * @throws IOException
         */
        public static void broadCastInfo(String message) throws IOException {
            for (Session session : SessionSet) {
                if(session.isOpen()){
                    sendMessage(session, message);
                }
            }
        }
    
        /**
         * 服务端指定 Session 推送消息
         * @param sessionId
         * @param message
         * @throws IOException
         */
        public static void sendMessage(String message, String sessionId) throws IOException {
            Session session = null;
            for (Session s : SessionSet) {
                if(s.getId().equals(sessionId)){
                    session = s;
                    break;
                }
            }
            if(session!=null){
                sendMessage(session, message);
            }
            else{
                log.warn("没有找到你指定ID的会话:{}", sessionId);
            }
        }
    }

    4、Controller 类:

    @Controller
    @RequestMapping("/template")
    public class TemplateController {
    
        // 跳转到 webSocket 测试页面
        @RequestMapping("/webSocket")
        public String websocket(ModelMap map) {
            return "websocket/index.html";
        }
    
    }
    @RestController
    @RequestMapping("/api/ws")
    public class WebSocketController {
    
        /**
         * 群发消息内容
         * @param message
         * @return
         */
        @RequestMapping(value="/sendAll", method=RequestMethod.GET)
        public String sendAllMessage(@RequestParam String message){
            try {
                WebSocketServer.broadCastInfo(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "OK";
        }
    
        /**
         * 指定会话ID发消息
         * @param message 消息内容
         * @param id 连接会话ID
         * @return
         */
        @RequestMapping(value="/sendOne", method=RequestMethod.GET)
        public String sendOneMessage(@RequestParam String message,@RequestParam String id){
            try {
                WebSocketServer.sendMessage(message, id);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "OK";
        }
    }

    5、测试页面:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>webSocket测试</title>
    </head>
    <body>
    
    
    <h3>WebSocket测试,在<span style="color:red">控制台</span>查看测试信息输出!</h3>
    
    <script type="text/javascript">
        if (typeof (WebSocket) == "undefined") {
            console.log("遗憾:您的浏览器不支持WebSocket");
        } else {
            console.log("恭喜:您的浏览器支持WebSocket");
            // 实例化WebSocket对象
            // 指定要连接的服务器地址与端口建立连接
            // 注意ws、wss使用不同的端口。我使用自签名的证书测试,
            // 无法使用wss,浏览器打开WebSocket时报错
            // ws对应http、wss对应https。
            socket = new WebSocket("ws://localhost:8087/ws/asset");
    
            // 连接打开事件
            socket.onopen = function () {
                console.log("Socket 已打开");
                socket.send("消息发送测试(From Client)");
            };
    
            // 收到消息事件
            socket.onmessage = function (msg) {
                console.log(msg.data);
            };
    
            // 连接关闭事件
            socket.onclose = function() {
                console.log("Socket已关闭");
            };
    
            // 发生了错误事件
            socket.onerror = function() {
                alert("Socket发生了错误");
            }
    
            // 窗口关闭时,关闭连接
            window.unload=function() {
                socket.close();
            };
    
    
        }
    
    
    </script>
    </body>
    </html>

    6、验证是否生效:

     

    参考链接:https://www.jianshu.com/p/2c9be4641d43

    艺无止境,诚惶诚恐, 感谢开源贡献者的努力!!
  • 相关阅读:
    已经加入了gitignore但任然modified
    强制升级方法
    从服务器上拷贝代码到虚拟机上编译不过
    IDEA 全局搜索选择后不关闭当前窗口
    jquery 好看的弹出层,过一会自动消失,有滚动条也能垂直居中(thymeleaf)( 代码库)
    Servlet 直接返回web前端(代码库)
    httpcore Immutable 升级替代方法
    重写equals-hashcode-标准方法(代码库)
    module的顺序影响jar包是从仓库来的,还是从其他module里来的
    AD登录过滤特殊字符,防止LDAP注入(代码库)
  • 原文地址:https://www.cnblogs.com/d0usr/p/11969265.html
Copyright © 2020-2023  润新知