汪的爱琪 2024-02-03 12:13 采纳率: 67.5%
浏览 5
已结题

http的threadlocal变量无法分享给ws的线程

http协议中的controller层
@PostMapping("/login")中,我定义登录成功返回jwt令牌,保存用户id和用户名

     String token = JWTUtils.generateToken(map);
                return Result.success(token);

在拦截器中,我将jwt令牌加入到threadlocal中,那么http的不同线程都可以访问到用户名和id

  @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");
        try{
            Map<String, Object>  claims =  JWTUtils.parseToken(token);
            ThreadLocalUtils.set(claims);
            return true;
        }catch (Exception e){
            response.setStatus(401);
            return false;
        }

    }

但是在websocket中使用threadlocal解析想要拿到用户id作为在线聊天socket聊天的唯一标识却拿不到,为map为null,就像这样

package com.codeCart.websocket;

import com.codeCart.util.ThreadLocalUtils;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket类是一个用于处理WebSocket通信的类。
 */
@ServerEndpoint("/websocket")
@Component
public class WebSocket {
    /**
     * 当WebSocket连接打开时调用的方法。
     *
     * @param session WebSocket会话对象
     */
    private static final Map<Integer,Session> sessions = new HashMap<>();
    private static  int onLineUser = 0;
    private Map<String,Object> map = ThreadLocalUtils.get();
    @OnOpen
    public void onOpen(Session session) {
        System.out.println(map);
        try{
            onLineUser++;
            sessions.put(onLineUser,session);
            session.setMaxIdleTimeout(1000*60*60*24);
            broadcastOnlineUser();
        }catch (Exception e){
            try {
                session.close();
            }catch (Exception x){
                System.out.println("连接未正常关闭!"+x.getMessage());
            }
            System.out.println("session创建失败原因"+e.getMessage());
        }
    }

    /**
     * 当WebSocket连接关闭时调用的方法。
     *
     * @param session WebSocket会话对象
     */
    @OnClose
    public void onClose(Session session) {
        sessions.remove(onLineUser);
        onLineUser--;
        broadcastOnlineUser();
    }

    /**
     * 当接收到WebSocket消息时调用的方法。
     *
     * @param message WebSocket消息
     * @param session WebSocket会话对象
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            Session receivingSession = sessions.get(2);
            receivingSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
                e.printStackTrace();
        }
    }


    /**
     * 当WebSocket发生错误时调用的方法。
     *
     * @param session WebSocket会话对象
     * @param error   WebSocket错误对象
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("websocket error:" + error.getMessage());
    }
    public void broadcastOnlineUser() {
        System.out.println("系统广播:当前在线用户数"+onLineUser);
    }


}


img


ps:我也知道通过ws协议传参校验,然后解析可以实现,或者通过一些方式周转拿到http消息的信息可以实现,但是我现在觉得既然我都用了threadlocal了,能不能同一件事情只做一次,ws也可以得到threadlocal的变量值

  • 写回答

3条回答 默认 最新

  • zcl_1991 2024-02-04 11:24
    关注

    WebSocket 默认又不经过拦截器

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 2月16日
  • 已采纳回答 2月8日
  • 修改了问题 2月3日
  • 创建了问题 2月3日

悬赏问题

  • ¥15 有人会用py或者r画这种图吗
  • ¥15 MOD04_3K图像预处理
  • ¥15 [VASP]关于超胞大小和k 点网格的收敛性测试
  • ¥15 pip下载paddle2onnx离谱错误
  • ¥60 db2move nlzxams import 导出db2备份数据报错
  • ¥15 关于#python#的问题:全文总结功能咨询
  • ¥15 俄罗斯方块中无法同时消除多个满行
  • ¥15 使用gojs3.0,如何在nodeDataArray设置好text的位置,再go.TextBlock alignment中进行相应的改变
  • ¥15 psfusion图像融合指标很低
  • ¥15 银河麒麟linux系统如何修改/etc/hosts权限为777