Spring Boot + WebSocket实现网页在线实时聊天

部分代码

首先创建springboot项目并引入依赖:

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

服务端核心代码

@Component
@ServerEndpoint("/chat/lobby")
public class LobbyChat {


    @OnOpen
    public void onOpen(Session session) throws IOException {
        /*
         * @description: TODO 链接建立时调用该方法
         * @params: [session]   //连接发起者的会话对象
         * @return: void
         * @author: QGQ
         * @dateTime: 2022/3/1 18:59
         */
//        Info.increaseOnlineCount();
        //从querystring中取出用户输入的用户名并解码然后和session对象一起保存到user对象中
        User user = new User(URLDecoder.decode(session.getQueryString().split("=")[1],"UTF-8"),session);
        Info.addUser(user);
        //向所有用户推送最新的在线者信息
        for (User u: Info.getUserList()) {
            send(u.getSession(),MsgHelper.generateUserInfo(Info.getUserList()));
        }
        System.out.println("一名用户上线,"+user.toString()+"当前在线人数为:"+ Info.getOnlineCount());
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        /*
         * @description: TODO 某用户下线,更新在线人数和在线者列表
         * @params: [session]
         * @return: void
         * @author: QGQ
         * @dateTime: 2022/3/1 19:01
         */
        System.out.println("用户"+Info.getUser(session)+"已下线,当前在线人数:"+(Info.getOnlineCount()-1));
        Info.removeUser(session);
        //向所有用户推送最新的在线者信息
        for (User u: Info.getUserList()) {
            send(u.getSession(),MsgHelper.generateUserInfo(Info.getUserList()));
        }
    }
    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("发生错误!");
        error.printStackTrace();
    }

    @OnMessage
    public void onMessage(String msg,Session session) throws IOException {
        /*
         * @description: TODO 根据收到消息的类型将收到的消息发给所有在线者或个人
         * @params: [session]
         * @return: void
         * @author: QGQ
         * @dateTime: 2022/3/1 19:51
         */
        //使用jackson的API将前端发来的封装好的消息对象转成map
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,String> received = objectMapper.readValue(msg, new TypeReference<Map<String,String>>(){});
//        System.out.println(received);
        String msgObj = null;   //用于封装规定格式的消息对象
        User sender = Info.getUser(session);    //获取发送者对象
        if (received.get("type").equals("lobby")){
            //该type值表示这是发往大厅的消息
            System.out.println("用户"+Info.getUser(session)+"发出的消息:"+received.get("content"));

            msgObj = MsgHelper.generateUserMsg(sender.getUsername(),sender.getSession().getId(),"lobby",received.get("content"));
            for (User u: Info.getUserList()) {
                send(u.getSession(),msgObj);
            }
        }
        if (received.get("type").equals("friend")){
            //该type值表示这条消息是发给某人的
            System.out.println(received);
            msgObj = MsgHelper.generateUserMsg(sender.getUsername(),sender.getSession().getId(),"friend",received.get("content"));
//            send(Info.getUser(session).getSession(),msgObj);
            send(Info.getUser(received.get("sessionID")).getSession(),msgObj);
        }
    }


    public static void send(Session receiver,String msg) throws IOException {
        /*
         * @description: TODO 向用户发送消息
         * @params: [receiver, msg] //前者为接受者,后者为发送的内容
         * @return: void
         * @author: QGQ
         * @dateTime: 2022/3/3 20:20
         */
        receiver.getBasicRemote().sendText(msg);
    }

}

前端核心代码:

let app = Vue.createApp({
    data(){
        return {
            username:"",    //当前用户的昵称
            lobby_input:"hello", //大厅输入框的内容
            friend_input:"",   //私聊输入框的内容
            msg_records_f: [],    //私聊框消息记录,格式为{type:"message",sender:xxx,senderID:xxx,to:xxx,time:xxx,content:xxx}
            msg_records_l:[],   //大厅消息记录,格式同上
            received_msg_f: "", //私聊框收到的最新消息
            online_count: 0,    //在线人数
            onlineUsers:null,   //在线者列表
            pri_chat_obj: {username:"未开始私聊",sessionId:-1}, //当前私聊对象,格式为{username:xxx,sessionID:xxx}
            socket: null,   //websocket对象
            btnChatMovedActiveIndex: -1,   //决定CSS类.btn-chat-moved是否生效
        }
    },
    methods:{
        sendMsgToF(){
          // 向私聊对象发送消息
          if(this.pri_chat_obj.sessionId != -1){
              if(this.friend_input!=""){
                  console.log(this.msgObjF);
                  this.socket?.send(this.msgObjF);
                  let d= new Date();
                  let timeStr = d.getHours() + "时" + d.getMinutes() +"分" + d.getSeconds() + "秒";
                  this.msg_records_f.push({sender:this.username,time:timeStr,content:this.friend_input});
                  this.friend_input = "";
              }
          }else {
              alert("请先选择私聊对象");
          }
        },
        sendMsgToL(){
          //发送消息到大厅,没输入任何文字时不发送
            if (this.lobby_input !== ""){
                this.socket?.send(this.msgObjL);
                this.lobby_input = "";
            }
        },
        chatWith(user){
          //切换私聊对象为user
            if(user!==this.pri_chat_obj){
                this.pri_chat_obj = user;
                this.msg_records_f = [];
            }
        },
        getUserBySessionID(id){
          //通过sessionID获取发送者对象
            for (let i = 0; i < this.onlineUsers.length; i++) {
                if (this.onlineUsers[i].sessionId === id){
                    return this.onlineUsers[i];
                }
            }
        }
    },
    computed:{
        msgObjL(){
            //要发送给后端的大厅消息对象,格式为{type:lobby,content:xxx}
            return  JSON.stringify({type:"lobby",content:this.lobby_input});
        },
        msgObjF(){
            //要发送给后端的私聊消息对象,格式为:{type:friend,sessionID:xxx,content:xxx}
            return  JSON.stringify({type:"friend",sessionID:this.pri_chat_obj.sessionId,content:this.friend_input});
        }
    },
    watch:{
        received_msg_f(val){
            console.log(val)
        }
    },
    mounted(){
        let name = window.prompt("请输入你在本次聊天中要使用的昵称");
        while (name === ""||name == null){
            name = window.prompt("请输入一个昵称!");
        }
        this.username = name;
        let webSocket = new WebSocket("ws://127.0.0.1:8080/chat/lobby?username="+this.username);
        webSocket.onopen = function (){
            console.log("链接建立成功");
            app.$data.socket = webSocket;
            // app.$data.online_count++;
        }
        webSocket.onclose = function (){
            console.log("连接已关闭");
        }
        webSocket.onerror = function (err){
            alert("连接服务器失败!");
            console.log(err);
        }
        //收到消息时调用
        webSocket.onmessage = function (event){
            console.log(event.data)
            let msgObj = JSON.parse(event.data);    //获取后端封装的消息对象
            // app.$data.received_msg_f = msgObj.content;  //修改最新收到的消息
            console.log(msgObj)
            if(msgObj.type==="message"){
                //该type值表示这是某个用户发送的消息
                if(msgObj.to==="lobby"){
                    app.$data.msg_records_l.push(msgObj);   //将收到的消息加入消息记录
                }
                if (msgObj.to==="friend"){
                    app.$data.msg_records_f.push(msgObj);
                    app.$data.pri_chat_obj = app.getUserBySessionID(msgObj.senderID);
                }
            }
            if (msgObj.type=="info"){
                //该type值表示这是服务器推送的在线用户信息
                // console.log(msgObj);
                app.$data.online_count = msgObj.onlineCount;
                app.$data.onlineUsers = msgObj.userList;
            }
        }
        //当窗口被关闭时,先关闭ws连接
        window.onbeforeunload = function (){
            webSocket.close();
            app.$data.socket = null;
            app.$data.online_count--;
        }

    }
}).mount("#app");

完整代码可在Gitee查看.

演示

先输入要使用的昵称
在这里插入图片描述
同样方法打开三个标签页
在这里插入图片描述
在大厅大消息所有人都会收到
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
鼠标在在线者列表上悬浮会出现chat按钮,点击可开始私聊
在这里插入图片描述
向私聊对象发送消息,只有他一个人会收到,Tony收到消息
在这里插入图片描述
Thor没有收到在这里插入图片描述
Peter收到Tony的回复
在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring-Boot WebSocket 可以实现向日葵远程控制。向日葵是一款远程控制软件,可以让我们在远程控制设备时更加方便和灵活。在使用Spring-Boot实现WebSocket时,我们可以结合向日葵的API来达到远程控制的目的。 首先,在Spring-Boot中,我们需要引入WebSocket的依赖。可以在pom.xml文件中添加相应的依赖,例如: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 然后,我们需要创建WebSocket的配置类。在配置类中,我们可以定义WebSocket的相关设置,例如消息处理器、握手拦截器等。可以参考以下代码: ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/myHandler").withSockJS(); } @Bean public WebSocketHandler myHandler() { return new MyHandler(); } } ``` 在以上代码中,`registerWebSocketHandlers` 方法用来注册WebSocket处理器,并指定了处理路径。`MyHandler` 是自定义的消息处理器,可以在其中处理接收到的消息、发送消息等。 接下来,我们可以在处理器中调用向日葵的API,实现远程控制的功能。例如: ``` public class MyHandler extends TextWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 处理接收到的消息 String receivedMessage = message.getPayload(); // 调用向日葵API,实现远程控制 // 发送消息 String responseMessage = "远程控制成功"; session.sendMessage(new TextMessage(responseMessage)); } } ``` 在以上代码中,`handleTextMessage` 方法用来处理接收到的消息。我们可以在其中调用向日葵的API实现远程控制的逻辑,并将结果作为消息发送回客户端。 最后,在Spring-Boot的主类中添加 `@EnableWebSocket` 注解,启用WebSocket功能。 综上所述,通过Spring-Boot WebSocket,我们可以便捷地实现向日葵远程控制的功能。使用WebSocket协议进行通信,同时结合向日葵的API,可以让我们更加灵活地远程控制设备。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值