ServerEndpoint报错详解
一、背景介绍
在现代Web应用中,WebSocket技术被广泛应用以实现实时通信,Spring Boot作为流行的Java框架,提供了对WebSocket的良好支持,在实际开发过程中,开发者可能会遇到各种问题和错误,本文将详细探讨在使用@ServerEndpoint注解时常见的报错及其解决方法,帮助开发者更好地理解和解决这些问题。

二、报错原因与解决方法
缺少@Component注解:在使用@ServerEndpoint注解的类上必须添加@Component注解,否则Spring无法管理这个Bean。
缺少ServerEndpointExporter配置:在Spring Boot项目中,需要配置ServerEndpointExporter来注册使用@ServerEndpoint注解的端点。
依赖未导入:确保在pom.xml中正确导入了springbootstarterwebsocket依赖。
Tomcat版本不兼容:WebSocket API要求Servlet容器支持,确保使用的是Tomcat 7及以上版本。
注入问题:由于WebSocket是多例的,每个连接对应一个对象实例,因此不能直接使用Spring的依赖注入。
1、缺少@Component注解

在使用@ServerEndpoint注解的类上必须添加@Component注解,否则Spring无法管理这个Bean。
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/ws/endpoint")
@Component
public class MyWebSocket {
// WebSocket相关方法
}2、缺少ServerEndpointExporter配置
在Spring Boot项目中,需要配置ServerEndpointExporter来注册使用@ServerEndpoint注解的端点。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}3、依赖未导入
确保在pom.xml中正确导入了springbootstarterwebsocket依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>springbootstarterwebsocket</artifactId>
</dependency>4、Tomcat版本不兼容

WebSocket API要求Servlet容器支持,确保使用的是Tomcat 7及以上版本,如果使用内嵌的Tomcat,可以通过以下配置确保版本:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>springbootstarterparent</artifactId>
<version>2.5.4</version>
<properties>
<tomcat.version>9.0.54</tomcat.version>
</properties>
</parent>5、注入问题
由于WebSocket是多例的,每个连接对应一个对象实例,因此不能直接使用Spring的依赖注入,可以通过以下方式解决:
使用静态变量和方法:利用静态变量和方法进行依赖注入。
private static RedisTemplateUtil redisTemplateUtil;
@Autowired
public void setRedisTemplateUtil(RedisTemplateUtil redisTemplateUtil) {
MyWebSocket.redisTemplateUtil = redisTemplateUtil;
}从Spring上下文中获取Bean:通过实现ApplicationContextAware接口手动获取Bean。
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
}然后在WebSocket中使用:
private RedisTemplateUtil redisTemplateUtil;
@OnOpen
public void onOpen(Session session) {
redisTemplateUtil = SpringUtils.getBean(RedisTemplateUtil.class);
}在使用@ServerEndpoint注解进行WebSocket开发时,可能会遇到多种报错,通过正确添加注解、配置ServerEndpointExporter、导入必要的依赖、确保Tomcat版本兼容以及合理处理依赖注入问题,可以有效解决这些报错,希望本文能帮助开发者更好地理解和解决@ServerEndpoint相关的报错问题,提高开发效率和代码质量。
五、Q&A
Q1: 为什么在使用@ServerEndpoint时需要添加@Component注解?
A1:@ServerEndpoint注解本身并不具备将类纳入Spring容器管理的功能,而@Component注解则负责将该类标记为Spring组件,使其能够被Spring容器扫描和管理,在使用@ServerEndpoint时,必须同时添加@Component注解,以确保Spring能够正确管理该WebSocket端点。
Q2: 如果遇到“javax.websocket.DeploymentException: Cannot deploy POJO class”错误,应该如何解决?
A2: 这个错误通常出现在尝试部署一个没有使用@ServerEndpoint注解的POJO类作为WebSocket端点时,为了解决这个问题,请确保你的WebSocket端点类使用了@ServerEndpoint注解,并且该注解位于类声明之上,还要检查是否有其他配置或代码导致Spring无法正确识别和部署该端点,如果问题依旧存在,请检查完整的堆栈跟踪信息以获取更多线索。
