精华内容
下载资源
问答
  • SpringBoot整合WebSocket
    2022-01-11 08:49:33


    一、什么是WebSocket?

    WebSocket是一种在单个TCP连接上进行全双工通信的协议。在理解WebSocket之前,我认为有必要说一下Http,以此来对照着理解WebSocket。在以往的Web开发中,通常是客户端(比如网站)调用服务端的接口来请求数据,在这次的前后端交互中,客户端是主动的,客户端通过Http请求来调用服务端接口,以此来获取数据,当数据拿到后,意味着本次的交互结束。这样的话,大家应该知道了,Http是客户端主动请求服务端数据,那么有没有一种技术,能够实现服务端主动向客户端推送数据呢?答案是肯定的,因此诞生了WebSocket协议,它是一种长久的,保持联系的交互方式,一旦客户端与服务端建立联系后,服务端便可实现与客户端的双向通信,并且一直保持着连接状态,直到客户端关闭连接为止。下面通过代码的方式来介绍WebSocket,本次的代码使用Springboot来实现,对Springboot还不了解的同学可以先行学习Springboot。

    二、导入WebSocket依赖

     		<!--webSocket-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
            </dependency>
            <!--工具类-->
            <dependency>
                <groupId>org.junit.platform</groupId>
                <artifactId>junit-platform-commons</artifactId>
            </dependency>
    

    三、新建配置类,开启WebSocket支持

    要想在SpringBoot项目中开启WebSocket,需要新建一个配置类。

    /**
     * @作者 yangs
     * @日期 2022/1/10
     * @描述 开启WebSocket支持
     */
    @Configuration
    public class WebSocketConfig {
    
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    
    }
    

    四、新建WebSocket服务器

    这个类其实就是WebSocket服务器,@ServerEndpoint注解配置的路径,供客户端连接。当项目启动后,WebSocket服务器也会启动,届时客户端就可通过我们配置的路径,与WebSocket建立连接,实现双向通信。WebSocket服务器提供了4个核心方法,被@OnOpen、@OnClose、@OnMessage、@OnError注解标注,当建立连接时、断开连接时、收到客户端信息时、发生错误时调用。

    /**
     * @作者 yangs
     * @日期 2022/1/10
     * @描述 webSocket服务器
     */
    @ServerEndpoint(value = "/wsServer/{userId}")
    @Component
    public class WebSocketServer {
    
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
    
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
        private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
    
        //接收userId
        private String userId = "";
    
        /**
         * 连接建立成功调用的方法
         */
        @OnOpen
        public void onOpen(Session session, @PathParam("userId") String userId) {
            this.session = session;
            this.userId = userId;
            if (webSocketMap.containsKey(userId)) {
                webSocketMap.remove(userId);
                webSocketMap.put(userId, this);
                //加入set中
            } else {
                webSocketMap.put(userId, this);
                //加入set中
                addOnlineCount();
                //在线数加1
            }
            System.out.println("用户连接:" + userId + ",当前在线人数为:" + getOnlineCount());
            try {
                sendMessage("我是服务端,你连接成功了!");
            } catch (IOException e) {
                System.out.println("用户:" + userId + ",网络异常!!!!!!");
            }
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            if (webSocketMap.containsKey(userId)) {
                webSocketMap.remove(userId);
                //从set中删除
                subOnlineCount();
            }
            System.out.println("用户退出:" + userId + ",当前在线人数为:" + getOnlineCount());
        }
    
        /**
         * 收到客户端消息后调用的方法
         */
        @OnMessage
        public void onMessage(String message, Session session) {
            System.out.println("用户消息:" + userId + ",报文:" + message);
            //可以群发消息
            //消息保存到数据库、redis
            if (StringUtils.isNotBlank(message)) {
                try {
                    //解析发送的报文
                    JSONObject jsonObject = JSON.parseObject(message);
                    //追加发送人(防止串改)
                    jsonObject.put("fromUserId", this.userId);
                    String toUserId = jsonObject.getString("toUserId");
                    //传送给对应toUserId用户的websocket
                    if (StringUtils.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)) {
                        webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                    } else {
                        System.out.println("请求的userId:" + toUserId + "不在该服务器上");
                        //否则不在这个服务器上,发送到mysql或者redis
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 发生错误时调用
         */
        @OnError
        public void onError(Session session, Throwable error) {
            System.out.println("用户错误:" + this.userId + ",原因:" + error.getMessage());
            error.printStackTrace();
        }
    
        /**
         * 实现服务器主动推送
         */
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
        }
    
        /**
         * 发送自定义消息
         */
        public static void sendInfo(String message, @PathParam("userId") String userId) throws IOException {
            System.out.println("发送消息到:" + userId + ",报文:" + message);
            if (StringUtils.isNotBlank(userId) && webSocketMap.containsKey(userId)) {
                webSocketMap.get(userId).sendMessage(message);
            } else {
                System.out.println("用户" + userId + ",不在线!");
            }
            System.out.println();
        }
    
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
    
        public static synchronized void addOnlineCount() {
            WebSocketServer.onlineCount++;
        }
    
        public static synchronized void subOnlineCount() {
            WebSocketServer.onlineCount--;
        }
    
    }
    

    上述代码提供了一个自定义的sendInfo(String message, String userId)方法,可以实现WebSocket向指定客户端推送数据,感兴趣的同学可以尝试调用一下,向某个客户端发送信息。实例:

    /**
     * @作者 yangs
     * @日期 2022/1/10
     * @描述 WebSocket服务端主动向客户端推送数据
     */
    @RestController
    @RequestMapping("/wsMessage")
    public class WsMessageController {
    
        /**
         * @作者 yangs
         * @日期 2022/1/10
         * @描述 webSocket服务端向其客户端推送数据
         */
        @GetMapping("/pushToCustomer")
        public void pushToCustomer(@RequestParam String toUserId, @RequestParam String message) throws IOException {
            WebSocketServer.sendInfo(message, toUserId);
        }
    
    }
    

    五、编写客户端代码

    客户端代码通过js实现,如下所示:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>长连接</title>
    </head>
    <body>
    <p>【userId】:
    <div><input id="userId" name="userId" type="text" value=""></div>
    <p>【toUserId】:
    <div><input id="toUserId" name="toUserId" type="text" value=""></div>
    <p>【contentText】:
    <div><input id="contentText" name="contentText" type="text" value="这是我发的消息"></div>
    <p>【操作】:
    <div><a onclick="openSocket()" style="cursor: pointer;">开启socket</a></div>
    <p>【操作】:
    <div><a onclick="sendMessage()" style="cursor: pointer;">发送消息</a></div>
    </body>
    <script src="js/jquery.min.js"></script>
    <script type="text/javascript">
        var socket;
    
        function openSocket() {
            if (typeof (WebSocket) == "undefined") {
                console.log("您的浏览器不支持WebSocket");
            } else {
                console.log("您的浏览器支持WebSocket");
                //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接
                var socketUrl = "http://localhost:4432/nld/wsServer/" + $("#userId").val();
                socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");
                console.log(socketUrl);
                if (socket != null) {
                    socket.close();
                    socket = null;
                }
                socket = new WebSocket(socketUrl);
    
                //打开事件
                socket.onopen = function () {
                    console.log("websocket已打开");
                    //socket.send("这是来自客户端的消息" + location.href + new Date());
                };
    
                //获得消息事件
                socket.onmessage = function (msg) {
                    console.log(msg.data);
                    //发现消息进入    开始处理前端触发逻辑
                };
    
                //关闭事件
                /*            socket.onclose = function () {
                                console.log("websocket已关闭");
                            };*/
    
                //发生了错误事件
                socket.onerror = function () {
                    console.log("websocket发生了错误");
                }
            }
        }
    
        function sendMessage() {
            if (typeof (WebSocket) == "undefined") {
                console.log("您的浏览器不支持WebSocket");
            } else {
                console.log("您的浏览器支持WebSocket");
                console.log('{"toUserId":"' + $("#toUserId").val() + '","contentText":"' + $("#contentText").val() + '"}');
                socket.send('{"toUserId":"' + $("#toUserId").val() + '","contentText":"' + $("#contentText").val() + '"}');
            }
        }
    </script>
    </html>
    

    总结

    以上便是SpringBoot整合WebSocket的全部代码,建议条件允许的同学按照上述代码运行一遍,看看效果。感谢阅读!

    更多相关内容
  • SpringBoot整合WebSocket+nacos注册中心实现多服务通信
  • springboot整合websocket

    2019-02-03 14:53:55
    springboot整合websocket
  • 针对springboot整合websocket实现长连接的实例,包含前后端内容
  • 主要介绍了通过实例讲解springboot整合WebSocket,WebSocket为游览器和服务器提供了双工异步通信的功能,即游览器可以向服务器发送消息,服务器也可以向游览器发送消息。,需要的朋友可以参考下
  • springboot整合 websocket 简单使用,里面有包括互相接发消息等简单方法
  • springboot整合WebSocket

    千次阅读 2022-04-27 16:45:47
    springboot整合WebSocket WebSocket通信过程 客户端构建一个websocket实例,并且为它绑定一个需要连接到的服务器地址,当客户端连接服务端的候,会向服务端发送一个http get报文,告诉服务端需要将通信协议切换到...

    springboot整合WebSocket

    WebSocket通信过程

    客户端构建一个websocket实例,并且为它绑定一个需要连接到的服务器地址,当客户端连接服务端的候,会向服务端发送一个http get报文,告诉服务端需要将通信协议切换到websocket,服务端收到http请求后将通信协议切换到websocket,同时发给客户端一个响应报文,返回的状态码为101,表示同意客户端协议转请求,并转换为websocket协议。以上过程都是利用http通信完成的,称之为websocket协议握手(websocket Protocol handshake),经过握手之后,客户端和服务端就建立了websocket连接,以后的通信走的都是websocket协议了。

    1.pom文件添加依赖

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

    2.启用Springboot对WebSocket的支持

    package com.lby.websocket.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    /**
     * @author Liby
     * @date 2022-04-25 16:18
     * @description:
     * @version:
     */
    @Configuration
    public class WebSocketConfig {
    
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    }
    
    

    3.核心配置:WebSocketServer

    因为WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller

    • @ ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端, 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
    • 新建一个ConcurrentHashMap webSocketMap 用于接收当前userId的WebSocket,方便传递之间对userId进行推送消息。

    下面是具体业务代码:

    package com.lby.websocket.component;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.springframework.stereotype.Component;
    import cn.hutool.core.util.StrUtil;
    import javax.websocket.*;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
    import java.io.IOException;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * @author Liby
     * @date 2022-04-25 16:21
     * @description:
     * @version:
     */
    @ServerEndpoint(value = "/websocket/{userId}")
    @Component
    public class WebSocket {
        private final static Logger logger = LogManager.getLogger(WebSocket.class);
    
        /**
         * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的
         */
    
        private static int onlineCount = 0;
    
        /**
         * concurrent包的线程安全Map,用来存放每个客户端对应的MyWebSocket对象
         */
        private static ConcurrentHashMap<String, WebSocket> webSocketMap = new ConcurrentHashMap<>();
    
        /**
         * 与某个客户端的连接会话,需要通过它来给客户端发送数据
         */
    
        private Session session;
        private String userId;
    
    
        /**
         * 连接建立成功调用的方法
         */
        @OnOpen
        public void onOpen(Session session, @PathParam("userId") String userId) {
            this.session = session;
            this.userId = userId;
            //加入map
            webSocketMap.put(userId, this);
            addOnlineCount();           //在线数加1
            logger.info("用户{}连接成功,当前在线人数为{}", userId, getOnlineCount());
            try {
                sendMessage(String.valueOf(this.session.getQueryString()));
            } catch (IOException e) {
                logger.error("IO异常");
            }
        }
    
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            //从map中删除
            webSocketMap.remove(userId);
            subOnlineCount();           //在线数减1
            logger.info("用户{}关闭连接!当前在线人数为{}", userId, getOnlineCount());
        }
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息
         */
        @OnMessage
        public void onMessage(String message, Session session) {
            logger.info("来自客户端用户:{} 消息:{}",userId, message);
    
            //群发消息
            /*for (String item : webSocketMap.keySet()) {
                try {
                    webSocketMap.get(item).sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }*/
        }
    
        /**
         * 发生错误时调用
         *
         * @OnError
         */
        @OnError
        public void onError(Session session, Throwable error) {
            logger.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
            error.printStackTrace();
        }
    
        /**
         * 向客户端发送消息
         */
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
            //this.session.getAsyncRemote().sendText(message);
        }
    
        /**
         * 通过userId向客户端发送消息
         */
        public void sendMessageByUserId(String userId, String message) throws IOException {
            logger.info("服务端发送消息到{},消息:{}",userId,message);
         if(StrUtil.isNotBlank(userId)&&webSocketMap.containsKey(userId)){
             webSocketMap.get(userId).sendMessage(message);
         }else{
             logger.error("用户{}不在线",userId);
         }
    
        }
    
        /**
         * 群发自定义消息
         */
        public static void sendInfo(String message) throws IOException {
            for (String item : webSocketMap.keySet()) {
                try {
                    webSocketMap.get(item).sendMessage(message);
                } catch (IOException e) {
                    continue;
                }
            }
        }
    
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
    
        public static synchronized void addOnlineCount() {
            WebSocket.onlineCount++;
        }
    
        public static synchronized void subOnlineCount() {
            WebSocket.onlineCount--;
        }
    
    }
    
    
    

    4.测试controller

    package com.lby.websocket.controller;
    
    import com.lby.websocket.component.WebSocket;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.io.IOException;
    
    /**
     * @author Liby
     * @date 2022-04-26 10:28
     * @description:建立WebSocket连接
     * @version:
     */
    @RestController
    @RequestMapping("/webSocket")
    public class WebSocketController {
        @Autowired
        private WebSocket webSocket;
        @PostMapping("/sentMessage")
        public void sentMessage(String userId,String message){
            try {
                webSocket.sendMessageByUserId(userId,message);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
    }
    
    

    5.webSocket网页客户端工具

    http://websocket.jsonin.com/
    

    在这里插入图片描述

    复制三个tab

    WebSocket地址分别输入后连接

    ws://127.0.0.1:8092/websocket/1
    ws://127.0.0.1.132:8092/websocket/2
    ws://127.0.0.1.132:8092/websocket/3
    

    在这里插入图片描述

    6.通讯测试

    1.往客户端发消息

    127.0.0.1:8092/webSocket/sentMessage?userId=1&message=请进入视频会议
    127.0.0.1:8092/webSocket/sentMessage?userId=2&message=请进入视频会议
    127.0.0.1:8092/webSocket/sentMessage?userId=3&message=请进入视频会议
    

    在这里插入图片描述

    2.客户端收到消息回复“好的”

    在这里插入图片描述

    在这里插入图片描述

    展开全文
  • 本文档简单介绍了web通讯的基本原理和springboot整合websocket的相关操作,具体操作请查看相关的网站,该文档仅做参考
  • Springboot整合Websocket

    2022-04-11 22:35:48
    websocketspringboot

    Springboot整合Websocket

    引入maven

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

    配置springboot

    server:
        port: 5003
    

    编写 ApplicationConfig 类配置websocket

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

    核心代码

    1. @ServerEndpoint(“/api/pushMessage/{userId}”) 前端通过此 URI 和后端交互,建立连接
    2. @Component 将此类交给 spring 管理
    3. @OnOpen websocket 建立连接的注解,前端触发上面 URI 时会进入此注解标注的方法
    4. @OnMessage 收到前端传来的消息后执行的方法
    5. @OnClose 顾名思义关闭连接,销毁 session
    6. 因为WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller
    7. 新建一个ConcurrentHashMap webSocketMap 用于接收当前userId的WebSocket,方便IM之间对userId进行推送消息

    测试代码

    @Component
    @Slf4j
    @ServerEndpoint("/api/pushMessage/{userId}")
    public class MyWebsocket {
        private Session session;
    
        private String userId;
    
        private static ConcurrentHashMap<String,MyWebsocket> webSocketSet = new ConcurrentHashMap<>();
        /**
         * 连接建立成功调用的方法
         * session为与某个客户端的连接会话,需要通过它来给客户端发送数据
         */
        @OnOpen
        public void OnOpen(Session session, @PathParam(value = "userId") String userId){
            log.info("----------------------------------");
            this.session = session;
            this.userId = userId;
            // userId是用来表示唯一客户端,如果需要指定发送,需要指定发送通过userId来区分
            webSocketSet.put(userId,this);
            log.info("[WebSocket] 连接成功,当前连接人数为:={}",webSocketSet.size());
            log.info("----------------------------------");
            log.info("");
    
            GroupSending(userId+" 来了");
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void OnClose(){
            webSocketSet.remove(this.userId);
            log.info("[WebSocket] 退出成功,当前连接人数为:={}",webSocketSet.size());
    
            GroupSending(userId+" 走了");
        }
    
        /**
         * 收到客户端消息后调用的方法
         */
        @OnMessage
        public void OnMessage(String message_str){
            log.info("[WebSocket] 收到消息:{}",message_str);
            //判断是否需要指定发送,具体规则自定义
            //message_str的格式 TOUSER:user2;message:aaaaaaaaaaaaaaaaaa;
            if(message_str.indexOf("TOUSER") == 0){
                //取出 name和message的值
                String[] split = message_str.split(";");
                String[] split1 = split[0].split(":");
                String[] split2 = split[1].split(":");
                String name = split1[1];
                String message = split2[1];
                //指定发送
                AppointSending(name,message);
            }else{
                //群发
                GroupSending(message_str);
            }
        }
    
        /**
         * 发生错误时调用
         * @param session
         * @param error
         */
        @OnError
        public void onError(Session session, Throwable error){
            log.info("发生错误");
            error.printStackTrace();
        }
    
        /**
         * 群发
         * @param message
         */
        public void GroupSending(String message){
            for (String name : webSocketSet.keySet()){
                try {
                    webSocketSet.get(name).session.getBasicRemote().sendText(message);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 指定发送
         * @param name
         * @param message
         */
        public void AppointSending(String name,String message){
            try {
                webSocketSet.get(name).session.getBasicRemote().sendText(message);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    

    测试websocket

    在线测试websocket网站: http://coolaf.com/tool/chattest

    展开全文
  • springboot整合websocket 最近在学习websocket,做份笔记和大家分享一下 1、引入相关依赖 springboot相关依赖就不写了,这里只写websocket的依赖 <!--websocket--> <dependency> <groupId>org....

    springboot整合websocket(一)简单聊天室

    springboot整合websocket(一)简单聊天室
    springboot整合websocket(二)聊天室补充篇

    springboot整合websocket(三)上传文件(引导篇)
    springboot整合websocket(四)上传文件(终篇)


    东西太多了,拆成几章来写(绝对不是骗流量^ w ^)

    这一部分就简单做一个公共聊天室吧

    1、引入相关依赖

    springboot相关依赖就不写了,这里只写websocket的依赖

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

    2、写配置文件

    这里注意不要漏了 @EnableWebSocket,用于开启websocket支持,同时 @Configuration将配置类注入spring容器

    package com.websocket.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.config.annotation.EnableWebSocket;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
    
    @Configuration
    //开启websocket支持
    @EnableWebSocket
    public class WebsocketConfig
    {
        /**
         * 必须要有的
         *
         * @return
         */
        @Bean
        public ServerEndpointExporter serverEndpointExporter()
        {
            return new ServerEndpointExporter();
        }
    
        /**
         * websocket 配置信息
         *
         * @return
         */
        @Bean
        public ServletServerContainerFactoryBean createWebSocketContainer()
        {
            ServletServerContainerFactoryBean bean = new ServletServerContainerFactoryBean();
            //文本缓冲区大小
            bean.setMaxTextMessageBufferSize(8192);
            //字节缓冲区大小
            bean.setMaxBinaryMessageBufferSize(8192);
            return bean;
        }
    }
    
    

    3、开始愉快的使用啦

    这里先介绍几个websocket的注解

    注解作用备注
    @ServerEndpoint用于声明websocket响应类,有点像@RequestMapping@ServerEndpoint("/websocket")
    @OnOpenwebsocket连接时触发参数有:Session session, EndpointConfig config
    @OnMessage有消息时触发参数很多,一会再说
    @OnClose连接关闭时触发参数有:Session session, CloseReason closeReason
    @OnError有异常时触发参数有:Session session, Throwable throwable

    3.1(重要) 将@ServerEndpoint标注在类上,然后依次创建4个方法,参数见上表,方法名随意

    注意类上需要有 @Component 扫描哦,我这里用的时@Controller

    @Log4j2
    @Controller
    @ServerEndpoint("/websocket")
    public class BaseWebsocketController
    {
    
    	//使用 ConcurrentHashMap, 保证线程安全, static全局共享 session
    	
    	//这里之所以static,是因为这个类不是单例的!!
    	//他虽然有@Controller注解,但是不适用Ioc容器中拿对象,每一次请求过来都是一个新的对象
    	
        //存放 session
        private final static Map<String, Session> sessions = new ConcurrentHashMap<>();
    
        //onopen 在连接创建(用户进入聊天室)时触发
        @OnOpen
        public void openSession(Session session, EndpointConfig config)
        {
            
        }
    
    	//响应字符串
        @OnMessage
        public void onMessage(Session session, String message)
        {
            
        }
    
    	//响应字节流
        @OnMessage
        public void onMessage(Session session, byte[] message)
        {
            
        }
    
        //onclose 在连接断开(用户离开聊天室)时触发
        @OnClose
        public void closeSession(Session session, CloseReason closeReason)
        {
            
        }
    
        @OnError
        public void sessionError(Session session, Throwable throwable)
        {
            
        }
    }
    
    

    说明

    细心的小伙伴可能发现,我有两个 @OnMessage, 这是因为websocket能发送三种请求(我知道的三种),一种是字符串,一种是字节流(用于上传文件),一种是ping-pong(乒乓机制),因为js不好发送ping请求,我这里就只有响应字符串和字节流两种方法。

    接下来的篇幅将只演示字符串的,字节流咱再另一篇说,不然太多了看的头痛

    3.2 往方法里面写点简单的东西

    里面注释写个很清楚哦,慢慢瞅,咱就解释一下流程
    1、再OnOpen中将session存起来,并通知其他用户,有人来啦。
    2、有消息来的时候,再OnMessage中,通知其他用户
    3、OnClose中,通知其他用户,别人溜了
    4、OnError中,有异常就关闭websocket

    @Log4j2
    @Controller
    @ServerEndpoint("/websocket")
    public class BaseWebsocketController
    {
    
        //使用 ConcurrentHashMap, 保证线程安全, static全局共享 session
    
        //这里之所以static,是因为这个类不是单例的!!
        //他虽然有@Controller注解,但是不适用Ioc容器中拿对象,每一次请求过来都是一个新的对象
    
        //存放 session
        private final static Map<String, Session> sessions = new ConcurrentHashMap<>();
    
        //onopen 在连接创建(用户进入聊天室)时触发
        @OnOpen
        public void openSession(Session session, EndpointConfig config)
        {
            //将session存起来, 用于服务器向浏览器发送消息
            sessions.put(session.getId(), session);
            sendAll("[" + session.getId() + "]进入房间");
        }
    
        //响应字符串
        @OnMessage
        public void onMessage(Session session, String message)
        {
            sendAll("[" + session.getId() + "]" + message);
        }
    
        //响应字节流
        @OnMessage
        public void onMessage(Session session, byte[] message)
        {
            //这个咱以后再说
        }
    
        //onclose 在连接断开(用户离开聊天室)时触发
        @OnClose
        public void closeSession(Session session, CloseReason closeReason)
        {
            //记得移除相对应的session
            sessions.remove(session.getId());
            
            sendAll("[" + session.getId() + "]离开了房间");
        }
    
        @OnError
        public void sessionError(Session session, Throwable throwable)
        {
            //通常有异常会关闭session
            try {
                session.close();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private void sendAll(String message)
        {
            for (Session s : sessions.values()) {
                //获得session发送消息的对象
                //Basic是同步, 会阻塞
                //Async是异步, 这个会有多线程并发导致异常, 发送消息太快也会有并发异常, 需要有 消息队列 来辅助使用
                final RemoteEndpoint.Basic remote = s.getBasicRemote();
                try {
                    //发送消息
                    remote.sendText(message);
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    3.3 写个页面使用websocket

    先上效果图

    在这里插入图片描述


    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
      <meta charset="UTF-8">
      <title>websocket-demo</title>
      
      <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css">
    </head>
    <body>
      <div class="container py-3">
        
        <div class="row">
          
          <div class="col-6">
            <div>
              <label for="messageArea">聊天信息:</label>
            </div>
            <div>
              <textarea id="messageArea" readonly class="w-100" style="height: 75vh;"></textarea>
            </div>
          </div>
          
          <div class="col">
            
            <div class="my-1">
              <label for="messageArea">用 户 名:</label>
            </div>
            
            <div class="my-1">
              <input type="text" id="username" autocomplete="off">
            </div>
            
            <div class="my-1">
              <button class="btn-info" id="joinRoomBtn">进入聊天室</button>
              <button class="btn-warning" id="leaveRoomBtn">离开聊天室</button>
            </div>
            
            <hr/>
            
            <div class="my-1">
              <label for="sendMessage">输入消息:</label>
            </div>
            <div>
              <textarea id="sendMessage" rows="5" class="w-100" style="max-height: 50vh"></textarea>
            </div>
            
            <div class="my-1">
              <button class="btn-primary" id="sendBtn">发送消息</button>
            </div>
          
          </div>
        
        </div>
      
      </div>
      
      <script src="https://s3.pstatp.com/cdn/expire-1-M/jquery/3.3.1/jquery.min.js"></script>
      
      <script>
        let webSocket;
        //ip和端口号用自己项目的
        //{websocket}: 其实是刚刚那个@ServerEndpoint("/websocket")中定义的
        let url = 'ws://127.0.0.1:8080/websocket';
        
        $('#username').keyup(function (e) {
          let keycode = e.which;
          if (keycode == 13) {
            $('#joinRoomBtn').click();
          }
        });
        
        //进入聊天室
        $('#joinRoomBtn').click(function () {
          let username = $('#username').val();
          webSocket = new WebSocket(url);
          webSocket.onopen = function () {
            console.log('webSocket连接创建。。。');
          }
          webSocket.onclose = function () {
            console.log('webSocket已断开。。。');
            $('#messageArea').append('websocket已断开\n');
          }
          webSocket.onmessage = function (event) {
            $('#messageArea').append(event.data + '\n');
          }
          webSocket.onerror = function (event) {
            console.log(event)
            console.log('webSocket连接异常。。。');
          }
        });
        
        //退出聊天室
        $('#leaveRoomBtn').click(function () {
          if (webSocket) {
            //关闭连接
            webSocket.close();
          }
        });
        
        //发送消息
        $('#sendBtn').click(function () {
          var msg = $('#sendMessage').val();
          if (msg.trim().length === 0) {
            alert('请输入内容');
            return;
          }
          webSocket.send($('#sendMessage').val());
          
          $('#sendMessage').val('');
        });
      
      </script>
    
    </body>
    </html>
    

    4、最后填下坑

    4.1@OnOpen、@OnMessage…那些参数是咋来滴?

    当然是看注释啦!转到源码,再类的上边有一大串注释,百度翻译看下就行。
    我上边的参数还有漏的哦~~太多了解释不过来。

    4.2 里面有一段是这个

    and Zero to n String or Java primitive parameters
    annotated with the {@link javax.websocket.server.PathParam} annotation for server endpoints.
    

    意思是可以再路径中加入参数,然后用 @PathParam注解获得该参数(是不是和web很像呢)

    也就是说,可以这样

    @ServerEndpoint("/websocket/{username}")
    

    然后这样获得参数(所有方法都可以加),而且可以不止一个

    //响应字符串
    @OnMessage
    public void onMessage(@PathParam("username") String username, Session session, String message)
    {
        sendAll("[" + username + "]" + message);
    }
    

    再html连接时,url就这么写

    let username = $('#username').val();
    let url = 'ws://127.0.0.1:8080/websocket';
    url = url+'/'+username;
    

    所以啊,刚刚我们demo的用户名是可以显示出来的(这个就交给大家了,懒 >_<)。

    End


    springboot整合websocket(一)简单聊天室
    springboot整合websocket(二)聊天室补充篇

    springboot整合websocket(三)上传文件(引导篇)
    springboot整合websocket(四)上传文件(终篇)

    展开全文
  • springboot整合websocket(三)上传文件(终篇) springboot整合websocket(一)简单聊天室 springboot整合websocket(二)上传文件(引导篇) 说明 这里就涉及到一个问题,文件保存在服务器,前端页面要等后端保存...
  • Springboot整合WebSocket经典案例WebSocker简介案例分析外部依赖包的导入application配置端口WebSocket配置类编写静态界面案例一:自己给自己发送消息案例二:群发消息(不包括自己) WebSocker简介 WebSocket是一种...
  • 在上一章对WebService进行了整合,本章将对WebSocket进行整合,后面会写两个小demo,本章将写一个进度条demo,后面会写一个聊天室demo。 WebSocket:用我自己的话来描述就是,正常的前后端使用是前端写一个请求,...
  • } script> body> html> 4. SpringBoot整合WebSocket 4.1 创建SpringBoot工程(引入WebSocket依赖) 如下图所示,选择Spring Initializr创建Springboot工程。选择对应的WebSocket组件。 通过查看pom.xml文件,我们...
  • springboot整合websocket的代码

    千次阅读 2022-04-16 00:12:17
    } function connect() { // websocket客户端的连接地址,此值等于WebSocketMessageBrokerConfigurer中registry.addEndpoint("/websocket-simple").withSockJS()配置的地址 var socket = new SockJS('/websocket-...
  • springboot整合websocket(二) springboot整合websocket(一) 接上一章,这次我们把文件上传的坑给填了 1、回顾一下 上次提到有一个方法: void onMessage(Session session, byte[] message); 这个是用来上传...
  • SpringBoot整合WebSocket实践

    千次阅读 2022-04-24 17:38:12
    先来看下维基百科WebSocket的简介: WebSocket是一种与HTTP不同的协议。两者都位于OSI模型的应用层,并且都依赖于传输层的TCP协议。 虽然它们不同,但是RFC 6455中规定:it is designed to work over ...
  • SpringBoot 整合WebSocket 简单实战案例》 地址:https://blog.csdn.net/qq_35387940/article/details/93483678 最简单直接的模式整合websocket,文章里介绍了怎么后端给前端广播推送消息,也介绍了前端之间怎么...
  • SpringBoot 整合WebSocket实现消息推送,WeSocket中使用@Autowired无法注入问题

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,958
精华内容 2,383
关键字:

springboot整合websocket

spring 订阅