[英]Convert Spring Websocket to Jetty Websocket
我開始將現有的Jetty 9應用程序webapp移至Spring Boot,但似乎無法弄清楚如何使用Jetty WebSocketHandler而不是Spring WebSocketHandler和WebSocketSession。
我可以在Application.java中正確設置Spring WebSocketHandler,並在Spring Framework文檔中找到JettyWebSocketHandlerAdaptor和JettyWebSocketSession類,但是我無法找到如何使用它或任何好的示例。
如何將WebSocketHandler移交給Jetty? 由於JettyWebSocketAdapter除了對象以外都不是其他任何東西,因此我一直在嘗試注冊Spring WebSocketHandler,然后將其所有方法都傳遞給JettyWebSocketHandler。 我這樣做很愚蠢:
應用程序
@EnableWebSocket
@SpringBootApplication
public class Application extends SpringBootServletInitializer implements WebSocketConfigurer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
SpringWSHandler springPlease = new SpringWSHandler();
registry.addHandler(springPlease, "/websocket").setHandshakeHandler(handshaker());
}
@Bean
public DefaultHandshakeHandler handshaker()
{
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
policy.setInputBufferSize(8192);
policy.setIdleTimeout(600000);
return new DefaultHandshakeHandler(new JettyRequestUpgradeStrategy(new WebSocketServerFactory(policy)));
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Spring WebSocketHandler
@Component
public class SpringWSHandler implements WebSocketHandler {
private JettyHandler jettyHandler;
private JettyWebSocketSession jettySession;
private static Logger logger = LoggerFactory.getLogger(SpringWSHandler.class);
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
logger.debug("Connection Established: " + session.getId());
jettySession = new JettyWebSocketSession(session.getAttributes());
jettyHandler = new JettyHandler(this, jettySession);
jettyHandler.onOpen(jettySession.getNativeSession());
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
logger.debug("Message from session: " + session.getId());
jettyHandler.onMessage(message.getPayload().toString());
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
//TODO
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
logger.debug("Closing the session: " + session.getId());
jettyHandler.onClose(closeStatus.getCode(), "Closing Connection");
session.close(closeStatus);
}
@Override
public boolean supportsPartialMessages() {
return true;
}
}
無論我打開網頁后,無論何時嘗試使用它,websocket連接都似乎關閉,它都會失敗。 一旦我嘗試使用jettyHandler的方法,連接就會關閉,該異常是ExceptionWebSocketHandlerDecorator異常:
11:44:27.530 [qtp1014565006-19] ERROR o.s.w.s.h.ExceptionWebSocketHandlerDecorator - Unhandled error for ExceptionWebSocketHandlerDecorator [delegate=LoggingWebSocketHandlerDecorator [delegate=org.appcad.webserver.jetty.SpringWSHandler@5a7b309b]]
java.lang.NullPointerException: null
直接使用Spring的WebSocketHandler或Jetty的WebSocketHandler,不要試圖像那樣混合它們。
您不能以這種方式使用Jetty WebSocketHandler
,因為它必須是Jetty LifeCycle層次結構的一部分,並且可以合理地訪問Jetty服務器。
正確的Jetty WebSocketHandler
訪問Spring層也很困難,因為Jetty和Spring之間的LifeCycle不會像這樣嚙合。
也許你可以使用WebSocketUpgradeFilter
和自定義實現WebSocketCreator
初始化你的目標是為WebSocket的,完全與事實后進入春季層。
每當發生新的傳入Websocket升級時,都會調用您的自定義WebSocketCreator
。
我暫時設法破解了一些可行的方法,但是很想聽聽使用Spring Boot結合使用Jetty WebSockets的更好,更合適的方法。
這使我可以將消息從Spring WebSocket傳遞到我的JettyWebSocketHandlerAdapter(JettyHandler)類,該類將消息傳遞給我的Jetty WebSocket和關聯的類。
Application.java中的WebSocketHandler設置
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
SpringWSHandler springPlease = new SpringWSHandler();
registry.addHandler(springPlease, "/websocket").setHandshakeHandler(factoryBean());
}
//Configure buffer size and timeouts
@Bean
public HandshakeHandler factoryBean()
{
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
policy.setInputBufferSize(8192);
policy.setIdleTimeout(3600000);
WebSocketServerFactory factory = new WebSocketServerFactory(policy);
return new DefaultHandshakeHandler(new JettyRequestUpgradeStrategy(factory));
}
SpringWSHandler.java
@Component
public class SpringWSHandler implements WebSocketHandler {
private JettyHandler jettyHandler;
private JettyWebSocketSession jettySession;
private static Logger logger = LoggerFactory.getLogger(SpringWSHandler.class);
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//Application.java adapts WebSocket connections to Jetty 9 API when registering handlers with the Jetty handshaker
//We can cast spring WebSocketSessions to JettyWebSocketSessions, and initialize the org.eclipse.jetty.websocket.api.Session with itself.
jettySession = (JettyWebSocketSession) session;
jettySession.initializeNativeSession(jettySession.getNativeSession());
//Setup our custom handler and populate the router, which was magically created by Spring using our annotated classes in Router and its dependencies.
jettyHandler = new ClothoJettyHandler(this, jettySession);
//Let the jetty web socket commence!
jettyHandler.onOpen(jettySession.getNativeSession());
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
logger.debug("Message from session: " + session.getId());
jettyHandler.onMessage(message.getPayload().toString());
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
//TODO
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
logger.debug("Closing the session: " + session.getId());
jettyHandler.onClose(closeStatus.getCode(), "Closing Connection");
session.close(closeStatus);
}
@Override
public boolean supportsPartialMessages() {
return true;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.