zoukankan      html  css  js  c++  java
  • 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上。

  • 相关阅读:
    安装VMtools vim编辑器的使用 压缩包命令 Linux下的用户管理 (第三天)
    VM虚拟机安装 常用Linux命令 网卡配置 (第二天)
    数据库的交互模式 常用的dos命令 (第一天)
    Validate US Telephone Numbers FreeCodeCamp
    Arguments Optional FreeCodeCamp
    Everything Be True FreeCodeCamp
    Binary Agents FreeCodeCamp
    Steamroller FreeCodeCamp
    Drop it FreeCodeCamp
    Smallest Common Multiple FreeCodeCamp
  • 原文地址:https://www.cnblogs.com/ginponson/p/6390975.html
Copyright © 2011-2022 走看看