Spring WebSocket 404错误的解决方法
近来学习 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 中步骤: 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; @EnableWebSocket public 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 上的经验都未解决该问题,直到查看到以下文章: 在此自己也做个记录避免以后遗忘。 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 @EnableWebSocket public 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 个方法: 实际上,如果只需要 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[] {"/"}; } } 重新部署后代开浏览器运行成功 客户端消息 服务器消息 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |