• Spring websocket浏览器连接时出现404错误


    1、场景

    在用websocket做一个简单的数据导入页面同步显示后台进度功能的时候,浏览器出现连接不上的错误:
    WebSocket connection to 'ws://localhost:8080/project/marco' failed: Error during WebSocket handshake: Unexpected response code: 404

    网上有很种导致404的情况,但是都没有用,我在这里记录一下我的情况。

    2、解决过程

    spring-websocket.xml的配置:

    <websocket:handlers>
    <websocket:mapping handler="messageHandler" path="/marco" />
    <websocket:handshake-interceptors>
      <bean class="com.project.websocket.HandshakeInterceptor"/>
    </websocket:handshake-interceptors>
    </websocket:handlers>
    
    <bean id="messageHandler" class="com.project.websocket.MessageHandler"/>
    

    查看打印的INFO级别日志,根据spring的启动信息我们可以看到:

    2017-02-09 21:57:40,559 INFO  [springframework.web.servlet.handler.SimpleUrlHandlerMapping] - Mapped URL path [/marco] onto handler of type [class org.springframework.web.socket.server.support.WebSocketHttpRequestHandler]
    

    WebSocketHttpRequestHandler通过SimpleUrlHandlerMapping注册了/marco地址,那应该是没错的啊,难道是客户端js的错误?

    var websocket = new WebSocket('ws://' + window.location.host + '/project/marco');
    

    地址好像也没错啊,和Spring in Action4里面的例子一样的啊。
    为什么地址没有映射到/marco?先看看DispatchServlet的handlerMappings有没有/marco先吧。

    断点DispatchServlet的doDispatch()方法,随便发起一个请求:

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ......
    	// Determine handler for the current request.
    	mappedHandler = getHandler(processedRequest);
    	if (mappedHandler == null || mappedHandler.getHandler() == null) {
    		noHandlerFound(processedRequest, response);
    		return;
    	}
        ......
    }
    

    进入getHandler(processedRequest)

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    	for (HandlerMapping hm : this.handlerMappings) {
    		if (logger.isTraceEnabled()) {
    			logger.trace(
    					"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
    		}
    		HandlerExecutionChain handler = hm.getHandler(request);
    		if (handler != null) {
    			return handler;
    		}
    	}
    	return null;
    }
    

    我们看一下handlerMappings里面的内容,不知道你们有没有找到/marco,反正我是没找到。
    言下之意,/marco没注册到?

    没办法,我们断点SimpleUrlHandlerMapping的registerHandlers()方法和DispatchServlet的initHandlerMappings()方法。

    我们看到SimpleUrlHandlerMapping的registerHandlers()先被执行。

    最后退出registerHandlers()方法,F6一路下来,从WebApplicationObjectSupport的initApplicationContext()方法中可以看到:

    • context.beanFactory.beanDefintionMap中包含[org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0->RootBeanDefintion]
    • 而且context.beanFactory.singletonObjects也包含了注册了/marco的SimpleUrlHandlerMapping实例。
    • 此时的context.configLocations是classpath:spring-context.xml

    DispatchServlet的initHandlerMappings()后被执行,我们来看这段:

    // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
    Map<String, HandlerMapping> matchingBeans =
        BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
    

    然而,在matchingBeans没有找到我们要的注册了/marco的SimpleUrlHandlerMapping。此时的context.configLocations是classpath*:spring-servlet.xml

    来到这里,你大概知道就是你的spring-websocket.xml放错位置啦。

    3、解决办法

    如果你的web.xml分开加载spring-context和spring-servlet的话,请将spring-websocket的资源文件放到spring-servlet上加载。
    注意:在spring-context加载的时候,你的messageHandler应该是还没有初始化,请不要注入到某个service上。

  • 相关阅读:
    【cs231n笔记】assignment1之KNN
    【数据】常用卫星遥感数据下载地址整理
    ArcGIS中重采样栅格像元匹配问题
    python调用HEG工具批量处理MODIS数据
    Google Earth Engine学习资源分享
    地表温度反演的单通道方法辩异
    Android Studio无法下载sdk的问题
    Anaconda常用命令
    AMSR-E/AMSR-2数据介绍与下载
    NASA HEG tool安装心得
  • 原文地址:https://www.cnblogs.com/ginponson/p/6390975.html
Copyright © 2020-2023  润新知