• 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上。

  • 相关阅读:
    undefined symbol 问题解决记录
    2021年中国数字人民币发展研究报告
    如何画出优秀的架构图
    用SIKT模型,让用户画像效果倍增
    全面总结图表设计
    如何用一周了解一个行业
    未来社区解决方案
    增长4大阶段,实现营销倍增的核心法则
    裂变营销的3个层次,让你实现指数增长
    运营的3个层面,让你轻松获得忠实用户
  • 原文地址:https://www.cnblogs.com/ginponson/p/6390975.html
Copyright © 2020-2023  润新知