玖语巴黎 2022-05-12 20:45 采纳率: 75%
浏览 154
已结题

Websocket异常 WebSocketSession not yet initialized

问题遇到的现象和发生背景

在创建Vue+Springboot前后端分离项目时,需要使用Websocket进行通讯,但是后端报了如下错误,不是每次但是经常

运行结果及报错内容
java.lang.IllegalStateException: WebSocketSession not yet initialized
    at org.springframework.util.Assert.state(Assert.java:76) ~[spring-core-5.3.19.jar:5.3.19]
    at org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.getPrincipal(WebSocketServerSockJsSession.java:87) ~[spring-websocket-5.3.19.jar:5.3.19]
问题相关代码

前端Websocket设置
vue.config.js

//配置websocket代理
proxyObj["/elitehrserver/ws"]={
    /*
    目前比较来看,无论是http还是ws都会后端都会偶尔出现WebSocketSession not yet initialized错误
    */
    target: "http://localhost:8081",
    changeOrigin: true
};

websocket的相关使用

        //websocket连接到后端服务器,并订阅消息
        connect(context){
            //创建连接后台服务器并返回实例
            context.state.stomp=Stomp.over(new SockJS(baseUrl+"/ws/ep"));
            let token=window.sessionStorage.getItem("token");
            //连接
            context.state.stomp.connect({"Auth-Token":token},success=>{
                //订阅消息(接口)并打印消息 /queue/chat 前面必须加 /user 这是规定
                context.state.stomp.subscribe("/user/queue/chat",msg=>{
                    let recieveMsg=JSON.parse(msg.body);
                    //如果不是当前对话用户或当前用户没和谁对话则展示消息通知
                    if(!context.state.currentSession||recieveMsg.from!==context.state.currentSession.username){
                        Notification({
                            title: "【"+recieveMsg.fromNickName+"】",
                            message: recieveMsg.content.length>10?recieveMsg.content.substr(0,10):recieveMsg.content,
                            position: 'bottom-right',
                            iconClass:"fa fa-comments"
                        });
                        //添加消息红点
                        Vue.set(context.state.idDot,context.state.currentAdmin.username+"#"+recieveMsg.from,true);
                    }
                    recieveMsg.notSelf=true;
                    recieveMsg.to=recieveMsg.from;
                    //添加同步消息
                    context.commit("addMessage",recieveMsg);
                })
            },error=>{

            })
        }

后端配置

/**
 * websocket配置类
 * @author 刘昌兴
 * 
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    /**
     * 添加endpoint,这样网页可以通过websocket连接上服务器
     * 也就是我们配置websocket的服务地址,并可以指定是否可以使用socketJS
     * @author 刘昌兴
     * 
     * @param registry
     * @return
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        /*
        * 1.将/ws/ep作为stomp的端点,用户连接了这个端点就可以进行websocket通讯,支持socketJS
        * 2.配置允许跨域
        * 3.支持socketJS访问
        */
        registry.addEndpoint("/ws/ep").setAllowedOriginPatterns("*").withSockJS();
    }
    /**
     * 输入通道参数配置
     * @author 刘昌兴
     * 
     * @param registration
     * @return
     */
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) {
                StompHeaderAccessor accessor= MessageHeaderAccessor.getAccessor(message,StompHeaderAccessor.class);
                //判断是否为连接,如果是则需要获取token,并设置用户对象,用于后续发送消息是获得发送来源等,而不是进行token认证,因为已经放行了/ws/**
                if(StompCommand.CONNECT.equals(accessor.getCommand())){
                    String token=accessor.getFirstNativeHeader("Auth-Token");
                    if(StringUtils.hasLength(token)){
                        String authToken=token.substring(tokenHead.length());
                        String username=jwtTokenUtil.getUserNameFromToken(authToken);
                        //如果token中存在用户名
                        if(StringUtils.hasLength(username)){
                            UserDetails userDetails=userDetailsService.loadUserByUsername(username);
                            //验证token是否有效,重新设置用户对象
                            if(jwtTokenUtil.validateToken(authToken,userDetails)){
                                UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
                                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                                accessor.setUser(authenticationToken);
                            }
                        }
                    }
                }
                return message;
            }
        });
    }
    /**
     * 配置消息代理
     * @author 刘昌兴
     * @param registry
     * @return
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //配置代理域,可以配置多个,配置代理目的地前缀为/queue,可以在配置域上向客户端推送消息
        registry.enableSimpleBroker("/queue");
    }
}
  • 写回答

3条回答 默认 最新

  • 歇歇 2022-05-20 02:59
    关注

    WebSocketSession尚未初始化

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月23日
  • 修改了问题 5月19日
  • 赞助了问题酬金10元 5月19日
  • 修改了问题 5月16日
  • 展开全部

悬赏问题

  • ¥15 MATLAB运行显示错误,如何解决?
  • ¥15 c++头文件不能识别CDialog
  • ¥15 Excel发现不可读取的内容
  • ¥15 UE5#if WITH_EDITOR导致打包的功能不可用
  • ¥15 关于#stm32#的问题:CANOpen的PDO同步传输问题
  • ¥20 yolov5自定义Prune报错,如何解决?
  • ¥15 电磁场的matlab仿真
  • ¥15 mars2d在vue3中的引入问题
  • ¥50 h5唤醒支付宝并跳转至向小荷包转账界面
  • ¥15 算法题:数的划分,用记忆化DFS做WA求调