zoukankan      html  css  js  c++  java
  • SpringBoot WebSocket实现前后端交互 (转)

    原文:https://www.cnblogs.com/xiaozhengtongxue/p/13448778.html

    • websocket: 在浏览器和服务器之间建立TCP连接,实现全双工通信
      springboot使用websocket有两种方式,一种是实现简单的websocket,另外一种是实现STOMP协议。本篇讲述如何使用springboot实现简单的websocket。

    直接在pom.xml中导入依赖。

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

    首先注入一个ServerEndpointExporterBean,该Bean会自动注册使用@ServerEndpoint注解申请的websocket endpoint,代码如下:

    @Component
    public class WebSocketConfig {
        @Bean
        public ServerEndpointExporter serverEndpointExporter(){
            return new ServerEndpointExporter();
        }
    }

    新建websocket  服务端,在其中处理websocket 逻辑

    @Component  //注册到容器中
    @ServerEndpoint("/webSocket")  //接收websocket请求路径
    @Slf4j
    public class WebSocket {
        //当前连接(每个websocket连入都会创建一个WebSocket实例)
        private Session session;
    
        //定义一个websocket容器存储session,即存放所有在线的socket连接
        private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();
    
        //处理连接建立
        @OnOpen
        public void opOpen(Session session){
            this.session = session;
            log.info("【有新的客户端连接了】:{}",session.getId());
            webSocketSet.add(this);  //将新用户加入在线组
            log.info("【websocket消息】有新的连接,总数:{}",webSocketSet.size());
        }
    
        //处理连接关闭
        @OnClose
        public void Onclose(){
            webSocketSet.remove(this);
            log.info("【websocket消息】连接断开,总数:{}",webSocketSet.size());
        }
    
        //接受消息
        @OnMessage
        public void onMessage(String message){
            log.info("【websocket消息】收到客户端发来的消息:{}",message);
        }
    
        // 群发消息
        public void sendMessage(String message) {
            for (WebSocket webSocket : webSocketSet) {
                log.info("【websocket消息】广播群发消息,message={}",message);
                try {
                    webSocket.session.getBasicRemote().sendText(message);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

    客户可以使用freeMarker模板工具实现。

    前端实现,建议:https://blog.csdn.net/LiLi_code/article/details/86583347

    由于部分浏览器可能不支持,可以先测试,代码如下:

    <script>
        var websocket = null;
        if('WebSocket' in window){
            websocket = new WebSocket('ws://localhost:8080/webSocket');
        }else{
            alert('当前浏览器不支持websocket消息通知');
        }
    
        //连接成功建立的回调方法
        websocket.onopen = function (event) {
            console.log("ws建立连接成功");
        }
    
        //连接关闭的回调方法
        websocket.onclose = function (event) {
            console.log("ws连接关闭");
        }
    
        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            /*setMessageInnerHTML(event.data);*/
           // alert("ws接收返回消息:"+event.data);
            console.log("服务器返回消息: " + event.data);
            //弹窗提醒(要用到JQuary,所以要先引入JQuary)   播放音乐
            $('#mymodal').modal('show')
        }
    
        //连接发生错误的回调方法
        websocket.onerror = function(event){
            alert('websocket通信发生错误!')
        }
    
        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function() {
            websocket.close();
        }
        </script>

    测试:(项目实现客户创建订单之后,前台发出提醒)

    @Autowired
    private WebSocket webSocket;
    
    @Override
        @Transactional
        public OrderDTO create(OrderDTO orderDTO) {//创建订单
            。。。。(具体代码省略)
    
           //创建新订单  发送websocket消息
            webSocket.sendMessage(orderDTO.getOrderId());
            return orderDTO;
        }

    添加新订单:


    接收到websocket消息



    前端实现,建议:https://blog.csdn.net/LiLi_code/article/details/86583347

    index.html
    
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>聊天室</title>
        </head>
        <body>
        <div id="main">
            <p>
                <input type="text" id="username" placeholder="请输入用户名"/>
                <button type="button" id="addBtn">加入</button>
            </p>
            <p>
                <input type="text" id="message" placeholder="请输入聊天信息"/>
                <button type="button" id="sendBtn" disabled>发送</button>
            </p>
            <ul id="msg"></ul>
        </div>
         
        </body>
        <script>
            window.onload = function () {
                //获取button对象
                let addBtn = document.getElementById("addBtn")
                let sendBtn = document.getElementById("sendBtn")
                let username = document.getElementById("username")
                var message = document.getElementById("message")
                //定义全局
                let ws = null;
                addBtn.onclick = function () {
                    join()
         
                }
         
                //给文本框添加键盘点击事件
                username.onkeyup = function (e) {
                    //如果输入的是回车,进聊天室
                    if (e.keyCode === 13) {
                        join()
                        username.disabled = true
                    }
                }
         
         
                sendBtn.onclick = function () {
                    sendMessage()
                }
                message.onkeyup = function(e){
                    if(e.keyCode === 13) sendMessage()
                }
         
                function join() {
                    addBtn.disabled = true
                    sendBtn.disabled = false
                    // 创建WebSocket对象,WebSocket使用的是ws协议
                    ws = new WebSocket('ws://localhost:2555')
                    ws.onopen = function () {
                        let username = document.getElementById("username").value
                        // 项服务器端发送消息
                        ws.send(
                                // 往后台发送json字符串
                                JSON.stringify({
                                    username: username,
                                    type: 'login'  //添加的对象
                                })
                        )
                    }
                    // onmessage与ws已经绑定,接受消息回来的时候还是会回到这里来
                    // 服务器发送消息后会触发
                    ws.onmessage = function (e) {
                        console.log(e.data)
                        //字符串对象转json对象
                        let data = JSON.parse(e.data)
                        let show
                        switch (data.type) {
                            case 'login': //新用户
                                show = `${data.username}加入了房间`
                                break;
                            case 'msg': // 有新的聊天信息
                                show = `${data.username} ${data.time} <br> ${data.message}`
                                break
                            case 'leave': //有人离开聊天室
                                show = `${data.username}离开了房间 ${data.time}`
                                break;
                        }
                        let li = document.createElement("li")
                        li.innerHTML = show
                        document.getElementById("msg").append(li)
                    }
                }
         
                function sendMessage() {
                    let username = document.getElementById("username").value
                    let msg = document.getElementById("message").value
                    //发送聊天消息给服务器
                    ws.send(JSON.stringify({
                        username: username,
                        message: msg,
                        type: 'msg'
                    }))
                    document.getElementById("message").value = ''
                }
            }
        </script>
        </html>
    app.js
    
        //后台服务器代码
        //引入websocket模块
        let ws = require('nodejs-websocket')
         
        //创建服务对象启动,监听端口号是2555
        let server = ws.createServer((conn)=>{
            console.log('有人连接...')
            //当客户端发消息时会触发text事件
            conn.on('text',(str)=>{
                let data = JSON.parse(str)
                console.log(data)
                //判断接受消息的类型
                switch(data.type){
                    case 'login': //新用户加入
                        conn.nickname = data.username //保存用户名属性
                        broadcast(
                            //发送json字符串告诉客户端有新用户加入
                            JSON.stringify({
                                username:data.username,
                                time:getTime(),
                                type:data.type
                            })
                        )
                        break
                    case 'msg':
                        broadcast(
                            JSON.stringify({
                                username:data.username,
                                time:getTime(),
                                message:data.message,
                                type:data.type
                            })
                        )
                        break
                }
            })
         
            //监听错误信息
            conn.on('error',(err)=>{
                console.log(err)
            })
         
            //监听断开连接
            conn.on('close',()=>{
                broadcast(
                    JSON.stringify({
                        username:conn.nickname,
                        time:getTime(),
                        type:'leave'
                    })
                )
            })
         
        }).listen(2555)
         
        //给所有客户端连接发送消息
        function broadcast(str){
            //遍历所有的客户端连接
            server.connections.forEach((conn)=>{
                //发送消息
                conn.send(str)
            })
        }
         
        function getTime(){
            var date = new Date();
            var hour = date.getHours();
            var min = date.getMinutes()
            var sec = date.getSeconds()
            return hour + ":" + min + ":" + sec
        }

    不要忘记实现导入websocket框架;

    1. 安装包 nodejs-websocket
    2. npm install nodejs-websocket
  • 相关阅读:
    【EFCORE笔记】自动生成属性的显式值
    【EFCORE笔记】更新数据的多种方案
    【EFCORE笔记】添加数据的多种方案
    【EFCORE笔记】多租户系统的最佳实践
    【EFCORE笔记】全局查询筛选器
    【EFCORE笔记】异步查询&工作原理&注释标记
    【EFCORE笔记】执行原始SQL查询
    003_Redis后台启动(windows10与)
    Office 2010后 如何保存新的样式集
    Mysql启动 发生系统错误 1067
  • 原文地址:https://www.cnblogs.com/lshan/p/14047527.html
Copyright © 2011-2022 走看看