一、场景
Springboot使用@ServerEndpoint来建立websocket链接。引入依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
配置Websocket
@Configuration @EnableWebSocket public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
二、报错信息
springboot项目添加websocket依赖后运行测试类报如下错误:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2024-01-15 10:27:30.908 ERROR 20552 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverEndpointExporter' defined in class path resource [org/springblade/lab/external/webScoket/WebSocketConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$211/1936375962.getObject(Unknown Source) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:929) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:591) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:164) at org.springblade.core.launch.BladeApplication.run(BladeApplication.java:49) at org.springblade.Application.main(Application.java:33) Caused by: java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available at org.springframework.util.Assert.state(Assert.java:76) at org.springframework.web.socket.server.standard.ServerEndpointExporter.afterPropertiesSet(ServerEndpointExporter.java:107) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ... 17 common frames omitted
三、排查思路
报的错误是创建ServerEndpointExporterBean失败,原因是ServerContainer不可用,那么我们就去看到ServerContainer在ServerEndpointExporter中是怎么注入的。
点进去ServerEndpointExporter()
类,
在第49行代码打上debug跑一下
选中第50行代码,右键,执行计算,或者使用快捷键Crtl+U
计算结果发现是null
四、分析原因
为什么servletContext会返回null,定位到 ServerContainer 类,发现他是一个接口,那必定注入的时候是有相应的实现类,点击查看实现,居然有五个实现类,那就可以推断是依赖冲突导致不知道要注入哪个实现,最后获取Bean的时候返回了null。
点进去getAttribute
方法,查看实现类
这里有五个实现类,三个是tomcat的,一个是undertow的,还有一个是springframework的,所以解决办法就是排除掉其他的实现类,只保留springframework
这个就行。
五、解决办法
安装Maven Helper
插件,打开项目的pom.xml
文件,点击pom文件左下角的Dependency Analyzer
排除掉多余的依赖。
最终结果:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!--添加以下排除方法--> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!--websocket服务--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <!--添加以下排除方法--> <exclusions> <exclusion> <artifactId>spring-boot-starter-web</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency>
再次启动,一切正常!