【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码)

这篇具有很好参考价值的文章主要介绍了【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码),SpringBoot,spring boot,websocket,后端

前言:

在当今互联网时代,实时通信已经成为了许多应用程序的基本需求。

而WebSocket作为一种全双工通信协议,为开发者提供了一种简单、高效的实时通信解决方案。

本文将介绍如何使用Spring Boot框架来实现WebSocket的集成,快速搭建实时通信功能。


什么是WebSocket?

WebSocket是一种在单个TCP连接上进行全双工通信的协议。与传统的HTTP请求-响应模式不同,WebSocket允许服务器主动向客户端推送数据,实现了实时通信的功能。WebSocket协议基于HTTP协议,通过在握手阶段升级协议,使得服务器和客户端可以直接进行数据交换,而无需频繁的HTTP请求。


Spring Boot中的WebSocket支持

Spring Boot提供了对WebSocket的支持,通过集成Spring WebSocket模块,我们可以轻松地实现WebSocket功能。在Spring Boot中,我们可以使用注解来定义WebSocket的处理器和消息处理方法,从而实现实时通信。


WebSocket和HTTP优劣势

【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码),SpringBoot,spring boot,websocket,后端

WebSocket的优势:
1.实时性:

​ WebSocket是一种全双工通信协议,可以实现服务器主动向客户端推送数据,实现实时通信。相比之下,HTTP是一种请求-响应模式 的协议,需要客户端主动发起请求才能获取数据。

2.较低的延迟:

​ 由于WebSocket使用单个TCP连接进行通信,避免了HTTP的握手和头部信息的重复传输,因此具有较低的延迟。

3.较小的数据传输量:

​ WebSocket使用二进制数据帧进行传输,相比于HTTP的文本数据传输,可以减少数据传输量,提高传输效率。

4.更好的兼容性:

​ WebSocket协议可以在多种浏览器和平台上使用,具有较好的兼容性。

HTTP的优势:
1.简单易用:

​ HTTP是一种简单的请求-响应协议,易于理解和使用。相比之下,WebSocket需要进行握手和协议升级等复杂操作。

2.更广泛的应用:

​ HTTP协议广泛应用于Web开发中,支持各种类型的请求和响应,可以用于传输文本、图片、视频等多种数据格式。

3.更好的安全性:

​ HTTP协议支持HTTPS加密传输,可以保证数据的安全性。

综上,WebSocket适用于需要实时通信和较低延迟的场景,而HTTP适用于传输各种类型的数据和简单的请求-响应模式。在实际应用中,可以根据具体需求选择合适的协议。


示例

版本依赖
模块 版本
SpringBoot 3.1.0
JDK 17
代码
WebSocketConfig
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
WebSocketServer
@Component
@ServerEndpoint("/server/{uid}")
@Slf4j
public class WebSocketServer {

    /**
     * 记录当前在线连接数
     */
    private static int onlineCount = 0;

    /**
     * 使用线程安全的ConcurrentHashMap来存放每个客户端对应的WebSocket对象
     */
    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    /**
     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 接收客户端消息的uid
     */
    private String uid = "";

    /**
     * 连接建立成功调用的方法
     * @param session
     * @param uid
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("uid") String uid) {
        this.session = session;
        this.uid = uid;
        if (webSocketMap.containsKey(uid)) {
            webSocketMap.remove(uid);
            //加入到set中
            webSocketMap.put(uid, this);
        } else {
            //加入set中
            webSocketMap.put(uid, this);
            //在线数加1
            addOnlineCount();
        }

        log.info("用户【" + uid + "】连接成功,当前在线人数为:" + getOnlineCount());
        try {
            sendMsg("连接成功");
        } catch (IOException e) {
            log.error("用户【" + uid + "】网络异常!", e);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (webSocketMap.containsKey(uid)) {
            webSocketMap.remove(uid);
            //从set中删除
            subOnlineCount();
        }
        log.info("用户【" + uid + "】退出,当前在线人数为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 会话
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("用户【" + uid + "】发送报文:" + message);
        //群发消息
        //消息保存到数据库或者redis
        if (StringUtils.isNotBlank(message)) {
            try {
                //解析发送的报文
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, String> map = objectMapper.readValue(message, new TypeReference<Map<String, String>>(){});
                //追加发送人(防止串改)
                map.put("fromUID", this.uid);
                String toUID = map.get("toUID");
                //传送给对应的toUserId用户的WebSocket
                if (StringUtils.isNotBlank(toUID) && webSocketMap.containsKey(toUID)) {
                    webSocketMap.get(toUID).sendMsg(objectMapper.writeValueAsString(map));
                } else {
                    //若果不在这个服务器上,可以考虑发送到mysql或者redis
                    log.error("请求目标用户【" + toUID + "】不在该服务器上");
                }
            } catch (Exception e) {
                log.error("用户【" + uid + "】发送消息异常!", e);
            }
        }
    }

    /**
     * 处理错误
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户【" + this.uid + "】处理消息错误,原因:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     * @param msg
     * @throws IOException
     */
    private void sendMsg(String msg) throws IOException {
        this.session.getBasicRemote().sendText(msg);
    }

    /**
     * 发送自定义消息
     * @param message
     * @param uid
     * @throws IOException
     */
    public static void sendInfo(String message, @PathParam("uid") String uid) throws IOException {
        log.info("发送消息到用户【" + uid + "】发送的报文:" + message);
        if (!StringUtils.isEmpty(uid) && webSocketMap.containsKey(uid)) {
            webSocketMap.get(uid).sendMsg(message);
        } else {
            log.error("用户【" + uid + "】不在线!");
        }
    }

    private static synchronized int getOnlineCount() {
        return onlineCount;
    }

    private static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    private static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }

}
WebSocketController
@RestController
public class WebSocketController {

    @GetMapping("/page")
    public ModelAndView page() {
        return new ModelAndView("webSocket");
    }

    @RequestMapping("/push/{toUID}")
    public ResponseEntity<String> pushToClient(String message, @PathVariable String toUID) throws Exception {
        WebSocketServer.sendInfo(message, toUID);
        return ResponseEntity.ok("Send Success!");
    }
}
webSocket.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>WebSocket消息通知</title>
</head>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
    var socket;

    //打开WebSocket
    function openSocket() {
        if (typeof (WebSocket) === "undefined") {
            console.log("您的浏览器不支持WebSocket");
        } else {
            console.log("您的浏览器支持WebSocket");
            //实现化WebSocket对象,指定要连接的服务器地址与端口,建立连接.
            var socketUrl = "http://localhost:8080/socket/server/" + $("#uid").val();
            //将https与http协议替换为ws协议
            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('{"toUID":"' + $("#toUID").val() + '","Msg":"' + $("#msg").val() + '"}');
            socket.send('{"toUID":"' + $("#toUID").val() + '","Msg":"' + $("#msg").val() + '"}');
        }
    }
</script>
<body>
<p>【uid】:
<div><input id="uid" name="uid" type="text" value="1"></div>
<p>【toUID】:
<div><input id="toUID" name="toUID" type="text" value="2"></div>
<p>【Msg】:
<div><input id="msg" name="msg" type="text" value="hello WebSocket2"></div>
<p>【第一步操作:】:
<div>
    <button onclick="openSocket()">开启socket</button>
</div>
<p>【第二步操作:】:
<div>
    <button onclick="sendMessage()">发送消息</button>
</div>
</body>

</html>
测试
打开2个页面

第一个:

http://localhost:8080/socket/page

【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码),SpringBoot,spring boot,websocket,后端

第二个:

http://localhost:8080/socket/page

【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码),SpringBoot,spring boot,websocket,后端

都点击开启socket

【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码),SpringBoot,spring boot,websocket,后端

都点击发送

【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码),SpringBoot,spring boot,websocket,后端

至此示例发送完成


总结

通过本文的介绍,我们了解了Spring Boot中如何集成WebSocket,实现实时通信的功能。

WebSocket作为一种高效的实时通信协议,为开发者提供了更好的用户体验和交互性。

希望本文能够帮助快速掌握Spring Boot整合WebSocket的方法,为应用程序添加实时通信功能。


源码获取

如果需要完整源码请关注公众号"架构殿堂" ,回复 "SpringBoot+WebSocket"即可获得


写在最后

感谢您的支持和鼓励! 😊🙏

如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot, spring cloud等系列文章,一系列干货随时送达!

【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码),SpringBoot,spring boot,websocket,后端文章来源地址https://www.toymoban.com/news/detail-752587.html

到了这里,关于【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [超详细]SpringBoot整合WebSocket

    WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它允许在浏览器和服务器之间进行实时的、双向的通信。相对于传统的基于请求和响应的 HTTP 协议,WebSocket 提供了一种更有效、更实时的通信方式,适用于需要实时更新、实时通知和实时交互的应用。 WebSocket 的一些关

    2024年02月11日
    浏览(43)
  • SpringBoot整合Websocket(Java websocket怎么使用)

    WebSocket 是一种基于 TCP 协议的全双工通信协议,可以在浏览器和服务器之间建立 实时、双向的数据通信 。可以用于在线聊天、在线游戏、实时数据展示等场景。与传统的 HTTP 协议不同,WebSocket 可以保持 长连接 ,实时传输数据,避免了频繁的 HTTP 请求和响应,节省了网络带

    2024年02月10日
    浏览(41)
  • 【十六】springboot整合WebSocket(超详细)

     springboot篇章整体栏目:  【一】springboot整合swagger(超详细 【二】springboot整合swagger(自定义)(超详细) 【三】springboot整合token(超详细) 【四】springboot整合mybatis-plus(超详细)(上) 【五】springboot整合mybatis-plus(超详细)(下) 【六】springboot整合自定义全局异常处

    2023年04月09日
    浏览(39)
  • WebSocket整合springboot显示进度条

    SpringBoot整合WebScoket显示进度条 - 钟小嘿 - 博客园 对于大文件上传解析,若直接上传,会超时,可使用WebSocket长链接方式实时显示文件的上传状态,实际上是从文件上传到内容解析完成存入数据库的过程,各个阶段的进度可自定义。 本文使用SpringBoot+WebSocket+vue2.0+Element+nginx实

    2024年02月14日
    浏览(42)
  • springboot整合websocket(详解、教程、代码)

    大家好,我是酷酷的韩~ 1.websocket定义 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。websocket 协议是在 http 协议上的一种补充协议,是 html5 的新特性,是一种持久化的协议。 2.websocket工作原理

    2024年02月02日
    浏览(61)
  • 【WebSocket】SpringBoot整合WebSocket实现聊天室(一)

    目录 一、准备 1、引入依赖 2、创建配置类 二、相关注解 首先我们需要在项目中引入依赖,有两种方式。第一种我们可以在创建Spring Boot项目时搜索WebSocket然后勾选依赖 第二种是我们可以直接在项目的pom.xml文件中插入以下依赖 我们需要进行如下配置 ServerEndpointExporter 是一个

    2024年02月13日
    浏览(50)
  • SpringBoot整合Netty+Websocket实现消息推送

           Netty是一个高性能、异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器和客户端。以下是Netty的主要优势: 高性能 :Netty基于NIO(非阻塞IO)模型,采用事件驱动的设计,具有高性能的特点。它通过零拷贝技术、内存池化技术等手段,进一步提高

    2024年01月20日
    浏览(45)
  • SpringBoot+Vue整合WebSocket实现实时通讯

            在开发过程中,我们经常遇到需要对前台的列表数据,实现实时展示最新的几条数据,或者是调度的任务进度条实现实时的刷新......,而对于这种需求,无状态的http协议显然无法满足我们的需求,于是websocket协议应运而生。websocket协议本质上是一个基于tcp的协议

    2024年02月13日
    浏览(41)
  • (一)SpringBoot 整合WebSocket 前端 uniapp 访问

    第一次使用WebSocket,所以最需要一个及其简单的例子,跑通之后,增加自己对该技术的理解。(技术基础介绍就免掉了,后面再补)  案例逻辑:目前只有一个用户,而且是一个用户给服务器发送数据,服务给该用户返回数据 此处的逻辑一共三步 第一步,添加依赖项 第二步

    2024年02月10日
    浏览(40)
  • Springboot 整合 WebSocket ,使用STOMP协议 ,前后端整合实战 (一)(1)

    server: port: 9908 3.WebSocketConfig.java import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springfra

    2024年04月25日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包