【SpringBoot】使用WebSocket做消息对话

Http协议只能客户端发送---服务器回复,

无法做到服务器主动向客户端发送消息,所以可以使用websocket来进行双向通道 发消息

 

研究了一下抖音 斗鱼的弹幕也是用的websocket,但是需要解密ws内容

可以使用拦截websocket 接管websocket的方式截取弹幕,做一个弹幕回复之类 游戏或者主播感谢回复 牛批哄哄的

 

 

后端:

pom载入websocket依赖

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

 

 

Springboot需要写个配置类

注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint

@Configuration
public class WebSocketConfig {

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



}

 

 

ws控制层各类事件处理和转发

package com.example.websocketdemo.websocket;

import cn.hutool.json.JSONObject;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@ServerEndpoint("/websocket/{name}")//开启websocket
@Component
public class WebSocket {

    private String name;//建立用户
    private Session session;//当前链接

    private static Map<String,WebSocket> allClients = new HashMap<>();


//    用户连接事件
    @OnOpen
    public void onOpen(@PathParam("name")String name ,Session session){
        System.out.println("连接建立:" + name);
        this.name =name;
        this.session = session;

//        存入链接用户名字和session
        allClients.put(name,this);
    }


//    接收消息事件
    @OnMessage
    public void onMessage(Session session,String message){
        System.out.println(message);
        System.out.println("接收消息事件");

        String to = new JSONObject(message).getStr("toUser");//获取目标接收者
        String toMessage =new JSONObject(message).getStr("toMessage");//获取发送的内容
        WebSocket webSocket = allClients.get(to);//获取目标接收者websocket


//        判断目标接收者是否为空
        if (webSocket !=null){
            Session tosession = webSocket.getSession();//获取接收方session
//            若链接是打开状态
            if (tosession.isOpen()){
                tosession.getAsyncRemote().sendText(toMessage);//找到链接的另外一端然后发消息
            }
        }else {
            session.getAsyncRemote().sendText("对方不在线");
        }



    }


//    关闭连接事件
    @OnClose
    public  void  OnClose(){
        System.out.println("关闭连接事件");
        allClients.remove(this.name);//清除掉已退出的用户
    }


    //    出现异常事件
    @OnError
    public void onError(Throwable e){
        System.out.println("出现异常事件");
    }

    public String getName() {
        return name;
    }

    public Session getSession() {
        return session;
    }

    public static Map<String, WebSocket> getAllClients() {
        Set<String> strings = allClients.keySet();
        for (String string : strings) {

        }
        return allClients;
    }


//    获取所有key
    public static ArrayList<String> getKey(){
        ArrayList<String> strings = new ArrayList<>();

        Set<String> keys = allClients.keySet();
        for (String string : keys) {
            strings.add(string);
        }
        return strings;
    }

}

 

 

前端:

一个简单的连接和对话页面,直接静态打开就能run

判断浏览器有没有WebSocket环境(一般都自带了 没有就是浏览器太垃圾 直接换)

需要注册一个WebSocket对象,和后端一样有各类事件触发


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript">
        function start() {
            alert(document.location.host)
        }

        var websocket = null;


        function connection() {
            var username = document.getElementById("name").value;
            if ('WebSocket' in window) {
                websocket = new WebSocket('ws://127.0.0.1:8080/websocket/' + username);

            } else {
                alert("当前浏览器没有WebSocket环境")
            }


            websocket.onopen = function () {
                document.getElementById("message").innerHTML = "链接已建立"
            };


            websocket.onmessage = function (event) {
                var data = event.data;
                document.getElementById("message").innerHTML = data;

            };

            websocket.onerror = function () {
                document.getElementById("message").innerHTML = "出现异常"
            };

            websocket.onclose = function () {
                document.getElementById("message").innerHTML = "链接已关闭"
            };


            // 监听窗口关闭事件
            window.onbeforeunload = function () {
                if (websocket != null) {
                    websocket.close()
                }
            }


        }

        // 发送
        function sendMessage() {
            var toUser = document.getElementById("toUser").value;
            var toMessage = document.getElementById("toMessage").value;

            if (websocket != null) {
                var message = '{"toUser":"' + toUser + '","toMessage":"' + toMessage + '"}';
                websocket.send(message);
            }

        }
    </script>
</head>

<body>
    <input type="text" id="name">
    <button onclick="connection()">链接</button><br>
    接收者:<input type="text" id="toUser"><br>
    内容:<input type="text" id="toMessage"><br>
    <button onclick="sendMessage()">发送</button>


    <span id="message"></span>

</body>

</html>

 

posted @ 2022-12-17 18:42  Hello霖  阅读(132)  评论(0编辑  收藏  举报