背景
笔者在springboot中使用JSR356的Websocket注解,然后各种方式尝试注入Bean,大多失效。
Spring MVC 4.x时代,推荐代码如下
@ServerEndpoint(value = "/WSAPI/Equipment/JobCounterReport/{dispatchNo}",configurator = SpringConfigurator.class)
经过多次尝试,还是错误了。如下
java.lang.IllegalStateException: Failed to find the root WebApplicationContext. Was ContextLoaderListener not used? at org.springframework.web.socket.server.standard.SpringConfigurator.getEndpointInstance(SpringConfigurator.java:70) ~[spring-websocket-5.1.19.RELEASE.jar:5.1.19.RELEASE] at io.undertow.websockets.jsr.EndpointSessionHandler.onConnect(EndpointSessionHandler.java:73) [undertow-websockets-jsr-2.0.32.Final.jar:2.0.32.Final] at io.undertow.websockets.jsr.JsrWebSocketFilter$1.handleUpgrade(JsrWebSocketFilter.java:165) [undertow-websockets-jsr-2.0.32.Final.jar:2.0.32.Final] at io.undertow.server.protocol.http.HttpReadListener.exchangeComplete(HttpReadListener.java:389) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at io.undertow.server.protocol.http.HttpServerConnection.exchangeComplete(HttpServerConnection.java:244) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at io.undertow.server.HttpServerExchange.invokeExchangeCompleteListeners(HttpServerExchange.java:1279) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at io.undertow.server.HttpServerExchange.terminateResponse(HttpServerExchange.java:1563) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at io.undertow.server.Connectors.terminateResponse(Connectors.java:159) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at io.undertow.server.protocol.http.HttpTransferEncoding$3.handleEvent(HttpTransferEncoding.java:199) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at io.undertow.server.protocol.http.HttpTransferEncoding$3.handleEvent(HttpTransferEncoding.java:197) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at io.undertow.conduits.HeadStreamSinkConduit.exitFlush(HeadStreamSinkConduit.java:192) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at io.undertow.conduits.HeadStreamSinkConduit.flush(HeadStreamSinkConduit.java:133) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at org.xnio.conduits.ConduitStreamSinkChannel.flush(ConduitStreamSinkChannel.java:162) [xnio-api-3.3.8.Final.jar:3.3.8.Final] at io.undertow.channels.DetachableStreamSinkChannel.flush(DetachableStreamSinkChannel.java:119) [undertow-core-2.0.32.Final.jar:2.0.32.Final] at org.xnio.channels.Channels.flushBlocking(Channels.java:63) [xnio-api-3.3.8.Final.jar:3.3.8.Final] at io.undertow.servlet.spec.ServletOutputStreamImpl.close(ServletOutputStreamImpl.java:619) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.spec.HttpServletResponseImpl.closeStreamAndWriter(HttpServletResponseImpl.java:534) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.spec.HttpServletResponseImpl.responseDone(HttpServletResponseImpl.java:623) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:328) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99) [undertow-servlet-2.0.32.Final.jar:2.0.32.Final] at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376) [undertow-core-2.0.32.Final.jar:2.0.32.Final]
解决方法1:静态注入
@Component @Slf4j @ServerEndpoint(value = "/WSAPI/Equipment/JobCounterReport/{dispatchNo}") public class WebSocketServer implements DynamicSQLCondition { public static ProcessOrderInfoMapper processOrderInfoMapper; @Autowired public void setProcessOrderInfoMapper(final ProcessOrderInfoMapper processOrderInfoMapper) { WebSocketServer.processOrderInfoMapper = processOrderInfoMapper; } }
解决方案2:自定义configurator
import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import javax.websocket.server.ServerEndpointConfig; /** * @author: passedbylove * @date: Created by 2022/3/19 22:20 * @version: 1.0.0 */ public class CustomSpringConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware { private static volatile BeanFactory context; public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException { return context.getBean(endpointClass); } @Override public void setApplicationContext(final ApplicationContext context) throws BeansException { this.context = context; }
@Configuration public class WebSocketConfiguration { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } @Bean public CustomSpringConfigurator customSpringConfigurator() { return new CustomSpringConfigurator(); } }
然后Websocket配置如下
@Component @Slf4j @ServerEndpoint(value = "/WSAPI/Equipment/JobCounterReport/{dispatchNo}",configurator = CustomSpringConfigurator.class) public class WebSocketServer implements DynamicSQLCondition { @Autowired private ProcessOrderInfoMapper processOrderInfoMapper; }
方法来自网络,版权归原作者所有
java - Springboot @ServerEndPoint "Failed to find the root WebApplicationContext." - Stack Overflow