VUE使用websocket

58,031次阅读
没有评论

共计 7658 个字符,预计需要花费 20 分钟才能阅读完成。

在之前搭建好的项目的基础上新版 security demo(二)前端 -CSDN 博客

目录

一、代码改造

1、后端改造

2、VUE 使用 websocket

3、测试

二、按用户推送

1、完整代码如下

1.1、前端

1.2、后端:

2、测试


一、代码改造

1、后端改造

(1)把 websocket 相关代码复制到 web 项目:

VUE 使用 websocket

VUE 使用 websocket

(2)添加白名单

web-socket 端口无需 token 验证,SecurityWebConfig 添加白名单

 @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {return (web) -> web.ignoring().requestMatchers("/param/**", "/user-websocket-endpoint/**","/menu-websocket-endpoint/**");
    }
2、VUE 使用 websocket

menumanage.vue 代码和这个类似。

3、测试

分别启动前后端,打开浏览器

(1)查看消息收发

VUE 使用 websocket

VUE 使用 websocket

VUE 使用 websocket

切换到菜单管理:

VUE 使用 websocket

再次切换到 user 页面,会断开之前的连接重新建立连接,因为 vue 每次进入页面都会执行 mounted。

idea 控制台打印:

VUE 使用 websocket

(2)postman 调用 user 发送消息接口

VUE 使用 websocket

浏览器接收成功:

VUE 使用 websocket

postman 调用 menu 发送消息接口:

VUE 使用 websocket

浏览器接收成功:

VUE 使用 websocket

二、按用户推送

 上面的 demo,所有的客户端都会接收到消息,现在希望推送给某个 user。则需要建立 WebSocketSession 和 userId 的关系,

(1)前端在 open 建立连接时发送 userId;




    WebSocket Client


    


(2)后端 WebSocketHandler 存储 userId 和 WebSocketSession 的映射关系

import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.CloseStatus;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Component
public class UserWebSocketHandler extends TextWebSocketHandler {private final ConcurrentMap userSessions = new ConcurrentHashMap();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {String userId = getUserIdFromSession(session);
        if (userId != null) {userSessions.put(userId, session);
            System.out.println("WebSocket connection established for userId:" + userId);
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {String userId = getUserIdFromSession(session);
        if (userId != null) {userSessions.remove(userId);
            System.out.println("WebSocket connection closed for userId:" + userId);
        }
    }

    public void sendMessageToUser(String userId, String message) throws IOException {WebSocketSession session = userSessions.get(userId);
        if (session != null && session.isOpen()) {session.sendMessage(new TextMessage(message));
        }
    }

    private String getUserIdFromSession(WebSocketSession session) {
        // Assuming userId is stored as a session attribute
        return (String) session.getAttributes().get("userId");
    }
}

(3)发送消息时根据 userId 检索目标 WebSocketSession。

1、完整代码如下
1.1、前端

1.2、后端:

(1)常量

package com.demo.security.ws.constant;

import lombok.Getter;
import org.springframework.web.socket.WebSocketSession;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class UserSessionConstant {

    @Getter
    private static Map sessionMap = new HashMap();

    public static void add(String userId,WebSocketSession session) {sessionMap.put(userId,session);
    }

    public static void remove(WebSocketSession session) {
        // 从 map 中找到 key,再 remove key
        //sessionMap.remove(userAccount);
    }
}

(2)ws 操作

package com.demo.security.ws;

import com.demo.security.dto.MsgDTO;
import com.demo.security.dto.UserDTO;
import com.demo.security.ws.constant.UserSessionConstant;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;

@Component
@Slf4j
public class UserWebSocketHandler extends TextWebSocketHandler {

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {//UserSessionConstant.add(session);
        log.info("user 有新的连接,sessionId:{}",session.getId());
    }

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 处理接收到的消息
        log.info("user 服务端 Received message: {}",message.getPayload());
        String payLoad = message.getPayload();
        ObjectMapper objectMapper = new ObjectMapper();
        MsgDTO msgDTO = objectMapper.readValue(payLoad, MsgDTO.class);
        UserSessionConstant.add(msgDTO.getUserAccount(),session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {UserSessionConstant.remove(session);
        log.info("user 连接已断开 sessionId:{}",session.getId());
    }

    public void sendMessageToAll(String message) {for(WebSocketSession session : UserSessionConstant.getSessionMap().values()) {if (session.isOpen()) {
                try {session.sendMessage(new TextMessage(message));
                    log.info("user 发送消息给 {} 成功",session.getId());
                } catch (IOException e) {e.printStackTrace();
                }
            }
        }
    }

    public void sendMessageToUser(String message,String userAccount) {for(String sessionUserAccount : UserSessionConstant.getSessionMap().keySet()){if(!userAccount.equals(sessionUserAccount)){continue;}
            WebSocketSession session = UserSessionConstant.getSessionMap().get(userAccount);
            if (session.isOpen()) {
                try {session.sendMessage(new TextMessage(message));
                    log.info("user 发送消息给用户 {} 成功",userAccount);
                } catch (IOException e) {e.printStackTrace();
                }
            }
        }
    }
}

(3)controller 接口

package com.demo.security.controller;


import com.demo.security.dto.UserDTO;
import com.demo.security.ws.UserWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/userMsg")
public class UserMsgController {

    @Autowired
    private UserWebSocketHandler userWebSocketHandler;

    @RequestMapping("/send")
    public void sendMessage(UserDTO messageDTO) {userWebSocketHandler.sendMessageToUser(messageDTO.toString(),messageDTO.getUserAccount());
    }
}
2、测试

(1)

打开两个浏览器,分别登录 zs、admin

VUE 使用 websocket

VUE 使用 websocket

后端断点可以看到 map 存储了两条数据:

VUE 使用 websocket

(2)调用 postman 接口给 zs 发送消息:

VUE 使用 websocket

查看浏览器,zs 的账号接收到了消息,admin 的没有接收到:

VUE 使用 websocket

原文地址: VUE 使用 websocket

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-10-07发表,共计7658字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)