首页 新闻 会员 周边 捐助

WebSocketSession not yet initialized

0
[已关闭问题] 关闭于 2022-05-24 15:56
问题遇到的现象和发生背景

在创建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");
    }
}

玖语巴黎的主页 玖语巴黎 | 菜鸟二级 | 园豆:202
提问于:2022-05-15 14:05
< >
分享
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册