Spring WebSocket出现404未找到错误

16

我正在尝试使用Spring创建一个WebSocket端点。但是每当我尝试从客户端连接时,都会收到404错误。我还有一个Java实现。

@ServerEndpoint(value = "/websocket")

现有某个运作良好的部分。以下是我的Spring实现代码,但它并没有运作。我在这里做错了什么?

package com.tlab.endpoint;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(socketHandler(),"/socket");;
    }

    @Bean
    public WebSocketHandler socketHandler() {
        return new SocketHandler();
    }

}

以下是处理程序

package com.tlab.endpoint;

import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;


public class SocketHandler extends TextWebSocketHandler {

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {

    }

}
在客户端代码中,我尝试了所有可能的不同组合,使用处理程序中的/socket。
var websocket = new WebSocket("ws://localhost:8080/tsim/socket");
var websocket = new WebSocket("ws://localhost:8080/tsim/socket");
var websocket = new WebSocket("ws://localhost:8080/tsim/rest/socket");

在处理程序中使用 /rest/socket

var websocket = new WebSocket("ws://localhost:8080/tsim/rest/socket");

其中 tsim 是我的上下文根。所有东西都抛出以下错误

WebSocket connection to 'ws://localhost:8080/tsim/socket' failed: Error during WebSocket handshake: Unexpected response code: 404.

我没有遇到任何编译和部署错误。我使用的是Tomcat 8.0,下面是调度器Servlet的配置。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:int-ftp="http://www.springframework.org/schema/integration/ftp"
       xmlns:batch="http://www.springframework.org/schema/batch"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:websocket="http://www.springframework.org/schema/websocket"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
            http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp.xsd
            http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
            http://www.springframework.org/schema/websocket
        http://www.springframework.org/schema/websocket/spring-websocket.xsd"
        >

    <import resource="classpath*:web-db-spring.xml"/>

     <context:component-scan base-package="com.traderslab.nseb,com.tlab.endpoint"/>

     <aop:aspectj-autoproxy/>

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="prefixJson" value="false"/>
                <property name="supportedMediaTypes" value="application/json"/>
                <property name="objectMapper">
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                        <property name="serializationInclusion" value="NON_NULL"/>
                    </bean>
                </property>
            </bean>
            <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <mvc:default-servlet-handler/>

</beans>

以下是我的web.xml

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/classes/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/rest/</url-pattern>
</servlet-mapping>

你在示例中显示了 ws://localhost:8080/tsim/socket,但错误消息显示为 ws://localhost:8080/TradeSim/socket。是 tsim 还是 TradeSim - Bogdan
我尝试了不同的方法...那部分我已经涵盖了,将其视为"tsim"或"TradeSim",这是上下文根。为了避免混淆,我会进行编辑。 - anandaravindan
2个回答

4

我终于自己找到了答案。由于这是由调度器servlet作为普通的http请求处理的。我需要在WebSocketConfig类中添加@Controller注释。

@Configuration
@EnableWebSocket
@Controller
public class WebSocketConfig implements WebSocketConfigurer

1
我正在使用Spring Boot,并且遇到了同样的问题,但是在WebSocketConfig中添加@Controller并没有帮助。出乎意料地,我得到了403错误。你能帮忙吗? - Greyshack
找到了解决方法。如果你想用浏览器测试 WebSocket,你需要添加 registry.addHandler(socketHandler(),"/socket").setAllowedOrigins("*");。 - Greyshack
请简要说明或编辑您的代码,以在此处使用 registry.addHandler(socketHandler(),"/socket").setAllowedOrigins("*")。 - susan097
@Greyshack 这只有在你的客户端运行在与你的服务器不同的域时才需要。例如,如果你的客户端运行在localhost:3000,而你的Spring服务器在localhost:8080上,那么你就需要它,但如果你的Spring服务器正在为客户端提供服务,则不需要。 - Jordan Mackie
3
这感觉有些不对。WebSocketConfig怎么会成为请求处理器呢?这就是@Controller的含义。现在你有一个既是控制器原型又是配置原型的bean。 - NealeU

0
在我的情况下,问题出在调度程序servlet映射上。我只有一个*.mvc映射,而websocket没有它,所以我不得不改成:
  <servlet-mapping>
     <servlet-name>dispatcherServlet</servlet-name>
     <url-pattern>*.mvc</url-pattern>
     <url-pattern>/</url-pattern>
  </servlet-mapping>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接