解决springboot -websocket项目打包报错

本文解决了一个常见的Spring Boot项目中WebSocket配置引发的打包错误。通过调整Maven打包参数和pom.xml配置,避免了测试阶段的冲突,确保了应用的正常部署。

报错日志内容:

2019-09-05 09:53:56.406  WARN 2432 --- [           main] o.s.w.c.s.GenericWebApplicationContext   : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverEndpointExporter' defined in class path resource [com/caiwei/webrtc/config/WebSocketConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
2019-09-05 09:53:56.411  INFO 2432 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-09-05 09:53:56.415 ERROR 2432 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverEndpointExporter' defined in class path resource [com/caiwei/webrtc/config/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:1778) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877) ~[spring-context-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:743) ~[spring-boot-2.1.7.RELEASE.jar:2.1.7.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:390) ~[spring-boot-2.1.7.RELEASE.jar:2.1.7.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) ~[spring-boot-2.1.7.RELEASE.jar:2.1.7.RELEASE]
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120) [spring-boot-test-2.1.7.RELEASE.jar:2.1.7.RELEASE]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) [spring-test-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365) [surefire-junit4-2.22.2.jar:2.22.2]
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273) [surefire-junit4-2.22.2.jar:2.22.2]
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238) [surefire-junit4-2.22.2.jar:2.22.2]
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159) [surefire-junit4-2.22.2.jar:2.22.2]
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384) [surefire-booter-2.22.2.jar:2.22.2]
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345) [surefire-booter-2.22.2.jar:2.22.2]
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126) [surefire-booter-2.22.2.jar:2.22.2]
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418) [surefire-booter-2.22.2.jar:2.22.2]
Caused by: java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
    at org.springframework.util.Assert.state(Assert.java:73) ~[spring-core-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.web.socket.server.standard.ServerEndpointExporter.afterPropertiesSet(ServerEndpointExporter.java:106) ~[spring-websocket-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
    ... 42 common frames omitted

 

原因及解决方式:

出现这个问题主要是因为打包package遇到test会冲突(冲突解释不准确),在打包的时候跳过test就可以了
mvn package -DskipTests 即 Springboot 打包跳过测试

在pom.xml <project>标签下的<properties>标签中加入<skipTests>true</skipTests>

 <properties>
        <skipTests>true</skipTests>
        <java.version>1.8</java.version>
    </properties>

 

<think>我们正在解决SpringBoot集成WebSocket时客户端连接报错:"no javax.websocket.server.servercontainer"的问题。根据引用内容,这个错误通常与`ServerEndpointExporter` bean的初始化失败有关,因为`javax.websocket.server.ServerContainer`不可用。错误原因分析:1.根据引用[1][2][4],错误信息`javax.websocket.server.ServerContainernot available`表明Spring在初始化`ServerEndpointExporter`时无法获取到`ServerContainer`。2.引用[3]提到,可能的原因包括项目依赖问题(如引入了wiremock等测试依赖未排除)或运行环境问题(如在单元测试中运行,而单元测试的上下文可能不包含WebSocket相关支持)。解决方案:步骤1:检查依赖确保在`pom.xml`(Maven)或`build.gradle`(Gradle)中正确引入了WebSocket依赖。对于Spring Boot,通常需要: ```xml<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency> ```同时,排除可能冲突的依赖,例如引用[3]中提到的wiremock。步骤2:检查配置类在Spring Boot中,我们需要一个配置类来注册WebSocket端点。通常,我们会定义一个`ServerEndpointExporter`bean。但是,请注意:-在非Web环境中(如单元测试或非Servlet容器),`ServerContainer`不可用,因此不应该创建`ServerEndpointExporter`。-确保`ServerEndpointExporter`仅在实际的Servlet容器环境中创建。例如,在配置类中:```java@Configurationpublic classWebSocketConfig {@BeanpublicServerEndpointExporterserverEndpointExporter() {returnnew ServerEndpointExporter();}}```但是,如果这个配置类在单元测试中被加载,就会因为缺少Servlet环境而报错。步骤3:处理单元测试环境如果错误发生在单元测试中(如引用[2]),我们可以通过以下方式避免在测试中创建`ServerEndpointExporter`:-使用`@Profile`注解,指定该bean只在生产环境(如"prod")中创建:```java@Configurationpublic classWebSocketConfig {@Bean@Profile("prod")//或者使用其他非测试的profilepublicServerEndpointExporterserverEndpointExporter() {returnnew ServerEndpointExporter();}}```然后在单元测试中激活一个不包含该bean的profile(如"test")。或者,使用条件注解`@ConditionalOnWebApplication`,确保只有在Web应用中才创建该bean:```java@Configurationpublic classWebSocketConfig {@Bean@ConditionalOnWebApplicationpublicServerEndpointExporterserverEndpointExporter() {returnnew ServerEndpointExporter();}}```步骤4:检查Servlet容器确保你使用的是支持WebSocket的Servlet容器(如Tomcat7.0.47+、Jetty9.0+等)。内嵌Tomcat是Spring Boot的默认容器,通常已经满足要求。步骤5:检查客户端连接方式客户端连接报错“no javax.websocket.server.servercontainer”可能意味着客户端试图连接到服务器端点时,服务器端并没有成功初始化WebSocket容器。因此,请确保服务器端已经正确配置并运行。如果以上步骤都检查无误,问题可能出在SpringBoot的自动配置上。可以尝试在启动类上添加`@EnableWebSocket`注解,但通常Spring Boot的starter已经包含。总结:根据引用内容,重点检查依赖、配置类(特别是`ServerEndpointExporter`的创建条件)和运行环境(确保在Servlet容器中运行)。如果问题仍然存在,请提供更多上下文信息,如完整的错误堆栈、依赖树和配置代码。相关问题:1.如何在SpringBoot中正确配置WebSocket?2.如何解决Spring Boot单元测试中的WebSocket初始化问题?3.如何排除SpringBoot项目中冲突的依赖?</think>### Spring Boot WebSocket 客户端连接报错解决方案 **问题分析** 报错 `no javax.websocket.server.servercontainer` 的根本原因是 Spring 容器无法初始化 `ServerEndpointExporter`,导致 WebSocket 服务端容器未正确创建[^1][^2][^4]。常见原因如下: 1. **依赖缺失或冲突** - 缺少 `spring-boot-starter-websocket` 依赖 - 存在冲突的测试依赖(如 WireMock 未排除)[^3] 2. **配置类问题** - `ServerEndpointExporter` 在非 Web 环境(如单元测试)中被错误加载[^2] - 未正确启用 WebSocket 支持 3. **运行环境问题** - 非 Servlet 3.0+ 容器(如旧版 Tomcat) - 非 Web 应用上下文(如 JUnit 测试) --- ### 解决方案 #### 步骤 1:检查依赖配置 确保 `pom.xml` 包含必要依赖并排除冲突项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <!-- 排除测试干扰项 --> <dependency> <groupId>com.github.tomakehurst</groupId> <artifactId>wiremock</artifactId> <scope>test</scope> <!-- 限制在测试环境 --> </dependency> ``` #### 步骤 2:修复配置类 在 `WebSocketConfig` 中添加环境检查: ```java @Configuration public class WebSocketConfig { // 仅当是 Web 环境时才注册 @Bean @ConditionalOnWebApplication public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } ``` #### 步骤 3:处理单元测试环境 在测试类中禁用 WebSocket 初始化: ```java @SpringBootTest @AutoConfigureMockMvc @TestPropertySource(properties = "spring.main.web-application-type=none") // 禁用 Web 环境 public class ApplicationTests { // 测试方法 } ``` #### 步骤 4:验证容器支持 检查内嵌容器版本(要求 **Servlet 3.0+**): ```properties # application.properties server.tomcat.version=9.0.xx # 确保 Tomcat ≥8.5 ``` #### 步骤 5:客户端连接示例 正确初始化客户端连接: ```java @ClientEndpoint public class WebSocketClient { @OnOpen public void onOpen(Session session) { System.out.println("Connected to endpoint: " + session.getBasicRemote()); } } // 连接代码 WebSocketContainer container = ContainerProvider.getWebSocketContainer(); container.connectToServer(WebSocketClient.class, URI.create("ws://localhost:8080/endpoint")); ``` --- ### 关键验证点 1. 启动日志中是否出现 `Mapping endpoint` 字样(表示 WebSocket 端点已注册) 2. 使用 `@ConditionalOnWebApplication` 避免非 Web 环境初始化[^4] 3. 确保客户端连接的 URL 与 `@ServerEndpoint` 注解路径一致 > 通过以上步骤,可解决 95% 的 `ServerContainer not available` 错误。若问题仍存在,需检查项目是否被错误打包为普通 JAR(非可执行 WAR),或容器是否禁用了 WebSocket 模块[^1][^3]。 --- ### 相关问题 1. 如何在 Spring Boot 中实现 WebSocket 的广播功能? 2. 如何解决 WebSocket 在负载均衡环境下的连接问题? 3. Spring Boot WebSocket 如何配置 SSL/TLS 加密? 4. 如何监控 WebSocket 的连接状态和消息流量? [^1]: 解决报错:javax.websocket.server.ServerContainer not available [^2]: SpringBoot启动单元测试报错javax.websocket.server.ServerContainer not available [^3]: springboot整合websocket报错:javax.websocket.server.ServerContainer not available [^4]: springbootwebsocket 打包报错java.lang.IllegalStateException: javax.websocket.server.Server...
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值