Springboot整合WebSocket实现主动向前端推送消息

这篇具有很好参考价值的文章主要介绍了Springboot整合WebSocket实现主动向前端推送消息。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

        在上篇文章tcp编程中,我们实现了C++客户端与java服务器之间的通信,客户端发送了一个消息给服务器,今天我们要实现基于WebSocket实现服务器主动向前端推送消息,并且以服务器接收到C++客户端的消息主动向前端推送消息的触发条件。

了解Websocket

WebSocket 的诞生背景

        在早期,网站为了实现推送技术,通常使用轮询(或称为短轮询)。轮询是指浏览器每隔一段时间向服务器发出 HTTP 请求,然后服务器返回最新的数据给客户端。这种方式存在明显的缺点:浏览器需要不断地向服务器发出请求,而每次请求都包含较长的头部信息,导致带宽资源浪费。

        为了解决这个问题,HTML5 定义了 WebSocket 协议,它能更好地节省服务器资源和带宽,并且能够更实时地进行通讯。

WebSocket 的基本原理

  1. WebSocket 是什么?

  • WebSocket 是一种网络传输协议,基于 TCP 实现。
  • 它在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。
  • 与 HTTP 不同,WebSocket 需要先创建连接,然后可以进行双向数据传输。
  1. WebSocket 握手过程

  • 客户端通过 WebSocket 构造函数创建 WebSocket 对象,连接到服务器的 WebSocket URL。
  • 客户端发送类似于 HTTP 请求的报文,服务器返回接受 WebSocket 协议的响应。
  • 握手成功后,客户端和服务器之间的 WebSocket 连接建立,后续数据以帧序列的形式传输。

WebSocket 与 HTTP 的区别

  • WebSocket 使用类似于 HTTP 的握手连接,但数据传输更高效。
  • 较少的控制开销:头部信息较小。
  • 更强的实时性:实时通信,避免等待请求响应。
  • 保持连接状态:WebSocket 是全双工通信,不需要反复发出请求。无需重新发起连接。
  • 更好的二进制支持:处理二进制内容。
  • 可以支持扩展:自定义子协议。

 WebSocket可以做什么

  • 推文
  • 广告
  • 聊天室
  • 公告消息

    ................... 

服务器端

打开idea,创建一个Springboot项目,添加WebSocket依赖

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

创建一个WebSocket控制类,代码如下

/**
 * WebSocket操作类
 */
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")  // 接口路径 ws://localhost:8081/webSocket/userId;
public class WebSocket {

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

    /**
     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     * 虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,
     * 所以可以用一个静态set保存起来。
     * 注:底下WebSocket是当前类名
     */
    private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();
    /**
     * 用来存所有在线连接用户信息,用来存每个session
      */
    private static ConcurrentHashMap<String,Session> sessionPool = new ConcurrentHashMap<String,Session>();
    /**
     * 链接成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value="userId")String userId) {
        try {
            this.session = session;
            this.userId = userId;
            webSockets.add(this);
            sessionPool.put(userId, session);
            log.info("【websocket消息】有新的连接,总数为:"+webSockets.size());
        } catch (Exception e) {
        }
    }
    /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        try {
            webSockets.remove(this);
            sessionPool.remove(this.userId);
            log.info("【websocket消息】连接断开,总数为:"+webSockets.size());
        } catch (Exception e) {
        }
    }
    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("【websocket消息】收到客户端消息:"+message);
    }

    /** 发送错误时的处理
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误,原因:"+error.getMessage());
        error.printStackTrace();
    }


    /**
     * 广播消息
      */
    public void sendAllMessage(String message) {
        log.info("【websocket消息】广播消息:"+message);
        for(WebSocket webSocket : webSockets) {
            try {
                if(webSocket.session.isOpen()) {
                    webSocket.session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 单点消息
      */
    public void sendOneMessage(String userId, String message) {
        Session session = sessionPool.get(userId);
        if (session != null&&session.isOpen()) {
            try {
                log.info("【websocket消息】 单点消息:"+message);
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 向多人发消息
     */
    public void sendMoreMessage(String[] userIds, String message) {
        for(String userId:userIds) {
            Session session = sessionPool.get(userId);
            if (session != null&&session.isOpen()) {
                try {
                    log.info("【websocket消息】 单点消息:"+message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

添加一个和上篇文章一样的ServerThread类,添加@Component注解并添加WebSocket的调用代码

@Component//注册为Springboot管理的bean,否则不能使用Springboot的其它bean
public class faceServerThread implements Runnable{
    @Autowired
    private studentDao dao;//用于访问数据库
    WebSocket webSocket=new WebSocket();//用于使用WebSocket中的方法
    @Override
    public void run() {
        try {
            ServerSocket server=new ServerSocket(8888);
            Socket socket;
            byte[] buffer = new byte[1024];
            int len;
            student stu;
            while(true)
            {
                socket=server.accept();//处于阻塞状态,直到客户端连接
                System.out.println("客户端连接成功");
                InputStream input=socket.getInputStream();//用于读取客户端发来的字节流
                while ((len=input.read(buffer))!=-1){
                    String str = new String(buffer, 0, len);
                    //此处为代码修改部分
                    stu=dao.selectById(str);
                    if(stu!=null){
                        System.out.println(str);
                        webSocket.sendOneMessage("0",str);
                    }
                    ///
                }
                System.out.println("接收消息完毕");
                //System.out.println("收到消息:"+id);
            }
        } catch (IOException e) {
            System.out.println("客户端连接失败:");
            e.printStackTrace();
        }
    }
}

此处实现了runnable接口,是为了另外开一条线程,不与Springboot冲突。 

在启动类中添加启动线程

@SpringBootApplication
public class FreshmandemoApplication {
	public static void main(String[] args){
        ConfigurableApplicationContext context=SpringApplication.run(FreshmandemoApplication.class, args);
        faceServerThread faceThread=context.getBean(faceServerThread.class);
        new Thread(faceThread).start();
    }
}

前端客户端 

添加一个HTML文件,实现WebSocket

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
</body>
<script type="text/javascript">
    var socket;
    if (typeof (WebSocket) == "undefined") {
        console.log("您的浏览器不支持WebSocket");
    } else {
        console.log("您的浏览器支持WebSocket");
        //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接
        var reqUrl = "http://localhost:8081/websocket/0" ;
        socket = new WebSocket(reqUrl.replace("http", "ws"));
        //打开事件
        socket.onopen = function () {
            console.log("Socket 已打开");
            //socket.send("这是来自客户端的消息" + location.href + new Date());
        };
        //获得消息事件
        socket.onmessage = function (msg) {
            console.log("onmessage--" + msg.data);
            //发现消息进入    开始处理前端触发逻辑
        };
        //关闭事件
        socket.onclose = function () {
            console.log("Socket已关闭");
        };
        //发生了错误事件
        socket.onerror = function () {
            alert("Socket发生了错误");
            //此时可以尝试刷新页面
        }
        //离开页面时,关闭socket
        //jquery1.8中已经被废弃,3.0中已经移除
        // $(window).unload(function(){
        //     socket.close();
        //});
    }

  /*  function sendMessage() {
        if (typeof (WebSocket) == "undefined") {
            console.log("您的浏览器不支持WebSocket");
        } else {
            // console.log("您的浏览器支持WebSocket");
            var toUserId = document.getElementById('toUserId').value;
            var contentText = document.getElementById('contentText').value;
            var msg = '{"sid":"' + toUserId + '","message":"' + contentText + '"}';
            console.log(msg);
            socket.send(msg);
        }
    }*/

</script>
</html>

测试

运行服务器,打开HTML文件,并开启浏览器控制台,打开上篇文章中的Qt客户端项目向后端服务器发送一个消息,

springboot websocket给前端发消息需要异步吗,spring boot,websocket,后端

可以看到Qt客户端向后端服务器发送一个消息的同时,浏览器控制台也接收到一个消息。文章来源地址https://www.toymoban.com/news/detail-840477.html

到了这里,关于Springboot整合WebSocket实现主动向前端推送消息的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Java:SpringBoot整合WebSocket实现服务端向客户端推送消息

    思路: 后端通过websocket向前端推送消息,前端统一使用http协议接口向后端发送数据 本文仅放一部分重要的代码,完整代码可参看github仓库 websocket 前端测试 :http://www.easyswoole.com/wstool.html 依赖 项目目录 完整依赖 配置 WebSocketServer.java 前端页面 websocket.html 前端逻辑 index.js 参

    2024年02月04日
    浏览(53)
  • websockets-后端主动向前端推送消息

    公司领导提出了一个新的需求,那就是部门主管在有审批消息的情况下,需要看到提示消息。其实这种需求最简单的方法使接入短信、邮件、公众号平台。直接推送消息。但是,由于使自研项目,公司领导不想花钱,只能另辟蹊径。 WebSocket协议是基于TCP的一种新的网络协议。

    2024年02月09日
    浏览(55)
  • SpringBoot+Netty+Websocket实现消息推送

    这样一个需求:把设备异常的状态每10秒推送到页面并且以弹窗弹出来,这个时候用Websocket最为合适,今天主要是后端代码展示。 添加依赖 定义netty端口号 netty服务器 Netty配置 管理全局Channel以及用户对应的channel(推送消息) 管道配置 自定义CustomChannelHandler 推送消息接口及

    2024年02月04日
    浏览(49)
  • 服务端(后端)主动通知前端的实现:WebSocket(springboot中使用WebSocket案例)

    我们都知道 http 协议只能浏览器单方面向服务器发起请求获得响应,服务器不能主动向浏览器推送消息。想要实现浏览器的主动推送有两种主流实现方式: 轮询:缺点很多,但是实现简单 websocket:在浏览器和服务器之间建立 tcp 连接,实现全双工通信 springboot 使用 websocket 有

    2023年04月14日
    浏览(68)
  • 前端实现消息推送、即时通信、SSE、WebSocket、http简介

    服务端主动向客户端推送消息,使客户端能够即时接收到信息。 场景 页面接收到点赞,消息提醒 聊天功能 弹幕功能 实时更新数据功能 短轮询 浏览器(客户端)每隔一段时间向服务器发送http请求,服务器端在收到请求后,不论是否有数据更新,都直接进行响应。 本质:客

    2024年02月16日
    浏览(43)
  • Springboot集成websocket实现消息推送和在线用户统计

    在启动类上添加一个bean 核心代码 实现消息推送只要在业务代码中调用sendMessageSpecial()方法即可。 然后调用刚才的业务接口测试:http://localhost:8080/websocket/t1 调用成功后可以看到三个窗口中都收到了消息

    2023年04月08日
    浏览(55)
  • SpringBoot集成WebSocket实现消息实时推送(提供Gitee源码)

    前言:在最近的工作当中,客户反应需要实时接收消息提醒,这个功能虽然不大,但不过也用到了一些新的技术,于是我这边写一个关于我如何实现这个功能、编写、测试到部署服务器,归纳到这篇博客中进行总结。 目录 一、什么是WebSocket 二、后端实现 2.1、引入pom.xml依赖

    2024年02月11日
    浏览(46)
  • 【Java】SpringBoot快速整合WebSocket实现客户端服务端相互推送信息

    目录 什么是webSocket? webSocket可以用来做什么? WebSocket操作类 一:测试客户端向服务端推送消息 1.启动SpringBoot项目 2.打开网站 3.进行测试消息推送 4.后端进行查看测试结果 二:测试服务端向客户端推送消息 1.接口代码 2.使用postman进行调用 3.查看测试结果         WebSocke

    2024年01月20日
    浏览(61)
  • SpringBoot集成WebSocket,实现后台向前端推送信息

    在一次项目开发中,使用到了Netty网络应用框架,以及MQTT进行消息数据的收发,这其中需要后台来将获取到的消息主动推送给前端,于是就使用到了MQTT,特此记录一下。 WebSocket协议是基于TCP的一种新的网络协议。它实现了客户端与服务器全双工通信,学过计算机网络都知道

    2024年01月16日
    浏览(47)
  • Spring Boot进阶(48):【实战教程】SpringBoot集成WebSocket轻松实现实时消息推送

            WebSocket是一种新型的通信协议,它可以在客户端与服务器端之间实现双向通信,具有低延迟、高效性等特点,适用于实时通信场景。在SpringBoot应用中,集成WebSocket可以方便地实现实时通信功能,如即时聊天、实时数据传输等。         本文将介绍如何在Sprin

    2024年02月09日
    浏览(61)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包