近來學習Spring WebSocket 時按照Spring IN ACTION 中示例編寫代碼,運行時瀏覽器報404 錯誤
WebSocket connection to 'ws://localhost/websocket/marco' failed: Error during WebSocket handshake: Unexpected response code: 404
按照Spring IN ACTION 中步驟:
首先,繼承AbstractWebSocketHandler,重載以下3 個方法:
- handleTextMessage 處理文本類型消息
- afterConnectionEstablished 新連接建立後調用
- afterConnectionClosed 連接關閉後調用
import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.AbstractWebSocketHandler;public class MarcoHandler extends AbstractWebSocketHandler { protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { System.out.println("Received message: " + message.getPayload()); Thread.sleep(2000); session.sendMessage(new TextMessage("Polo!")); } @Override public void afterConnectionEstablished(WebSocketSession session) { System.out.println("Connection established!"); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { System.out.println("Connection closed. Status: " + status); }}其次,使用JavaConfig 啟用WebSocket 並映射消息處理器
import org.springframework.context.annotation.Bean;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(marcoHandler(), "/marco"); } @Bean public MarcoHandler marcoHandler() { return new MarcoHandler(); }}最後,編寫前端JS 代碼發起連接請求及後續消息交互
var url = 'ws://' + window.location.host + '/websocket/marco';var sock = new WebSocket(url);sock.onopen = function() { console.log('Opening'); sock.send('Marco!');};sock.onmessage = function(e) { console.log('Received Message: ', e.data); setTimeout(function() { sayMarco() }, 2000);};sock.onclose = function() { console.log('Closing');};function sayMarco() { console.log('Sending Marco!'); sock.send('Marco!');}部署後打開瀏覽器運行,直接報404 錯誤
上網搜索了一晚上解決方案,包括參考stackoverflow.com 上的經驗都未解決該問題,直到查看到以下文章:
Spring集成webSocket頁面訪問404問題的解決方法
在此自己也做個記錄避免以後遺忘。
WebSocket 實質上借用HTTP 請求進行握手,啟用Spring WebSocket 需要在org.springframework.web.servlet.DispatcherServlet 裡配置攔截此請求。
以下是解決步驟:
首先,修改WebSocketConfig 類定義,在類上添加@Configuration 註解,表明該類以JavaConfig 形式用作bean 定義的源(相當於XML 配置中的<beans> 元素)。
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(marcoHandler(), "/marco"); } @Bean public MarcoHandler marcoHandler() { return new MarcoHandler(); }}其次,使用JavaConfig 配置DispatcherServlet,繼承org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer ,重載以下3 個方法:
- getRootConfigClasses 返回帶有@Configuration 註解的類將會用來配置ContextLoaderListener 創建的應用上下文中的bean
- getServletConfigClasses 返回帶有@Configuration 註解的類將會用來定義DispatcherServlet 應用上下文中的bean
- getServletMappings 將一個或多個路徑映射到DispatcherServlet 上
實際上,如果只需要Spring WebSocket 生效,則只需要在getServletConfigClasses 方法中返回用來定義DispatcherServlet 應用上下文中的bean
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;public class WebSocketInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return null; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] {WebSocketConfig.class}; } @Override protected String[] getServletMappings() { return new String[] {"/"}; }}重新部署後代開瀏覽器運行成功
客戶端消息
服務器消息
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。