最近用SpringBoot整合WebSocket时遇到的前端连接不上404错误错误提示如下:
WebSocket connection to 'ws://127.0.0.1:8091/ws/asset' failed:
Error during WebSocket handshake: Unexpected response code: 404
架构版本:
IDEA:2019.3.1
SpringBoot:2.2.6
Tomcat:9.0.33
JDK:1.8
pom依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.cv</groupId>
<artifactId>websocket</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBoot-WebSocket</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml配置:
server:
port: 8091
servlet:
context-path: /spring-ws
spring:
mvc:
static-path-pattern: /static/**
WebSocket配置:
package org.cv.websocket.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* Created by Ale on 2020/4/1
* 首先要注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket
* endpoint。
* 要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入
* ServerEndpointExporter,
* 因为它将由容器自己提供和管理
*/
@Configuration
public class WebSocketConfig{
@Bean
public ServerEndpointExporter exporter() {
return new ServerEndpointExporter();
}
}
WebServer:
package org.cv.websocket.server;
import org.cv.websocket.entity.Client;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by Ale on 2020/4/1
*/
@Component
@ServerEndpoint(value = "/ws/asset")
public class WebSocketServer {
Logger logger = LoggerFactory.getLogger(getClass());
/**
* TODO: 这里只是测试连接,其他暂时不加进来..
*/
/**
* 连接数
*/
private static long onConnectCount = 0;
/**
* 用线程安全的ConcurrentHashMap 来存放客户端信息
*/
private static ConcurrentHashMap<String, Client> concurrentHashMap = new ConcurrentHashMap<>();
/**
* 由WebSocket提供的Session
*/
private static Session session;
/**
* 服务端名称
*/
private static final String SYS_NICK_NAME = "SYSADMIN";
@OnOpen
public void onOpen(Session session){
this.session = session;
logger.info("有新连接进入...");
}
// @OnError
// public void onError(){
// System.out.println("握手失败");
// }
}
前端:
let socket = new WebSocket('ws://127.0.0.1:8091/ws/asset');
socket.onopen = (e) => {
console.log('连接成功');
console.log(e);
}
只是为了测试连接所以就没有写的太严格。回到404错误,发生404的情况呢一般就是路径错误,结合yml项目路径在看看前端的路径写法,发现少了spring-ws。ok找到问题所在。
在这之前也在网上收集各种资料为什么会发生404错误,结果呢很多解释说tomcat版本问题或者其他一些问题,但在这里我想说遇到问题一定要先结合自己的框架,针对性的解决,这边呢还有一个坑建议亲踩一下:
javax.websocket.DeploymentException:
No Throwable parameter was present on the method [onError] of class
[org.cv.websocket.server.WebSocketServer] that was annotated with OnError
什么意思呢,也就是说用OnError注释标注的方法没有Throwable 这个参数,那么就会导致启动时候直接报错。所以在写OnError方法时一定要记得加上,一定要加上,加上。