簡體   English   中英

將Spring Websocket轉換為Jetty Websocket

[英]Convert Spring Websocket to Jetty Websocket

我開始將現有的Jetty 9應用程序webapp移至Spring Boot,但似乎無法弄清楚如何使用Jetty WebSocketHandler而不是Spring WebSocketHandler和WebSocketSession。

我可以在Application.java中正確設置Spring WebSocketHandler,並在Spring Framework文檔中找到JettyWebSocketHandlerAdaptor和JettyWebSocketSession類,但是我無法找到如何使用它或任何好的示例。

http://docs.spring.io/autorepo/docs/spring-framework/4.1.9.RELEASE/javadoc-api/org/springframework/web/socket/adapter/jetty/JettyWebSocketHandlerAdapter.html

如何將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM