SpringWebSocket404错误的解决⽅法
近来学习 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: " + Payload());
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);
spring framework}
}
其次,使⽤ JavaConfig 启⽤ WebSocket 并映射消息处理器
import t.annotation.Bean;
import org.springframework.fig.annotation.EnableWebSocket;
import org.springframework.fig.annotation.WebSocketConfigurer;
import org.springframework.fig.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);
console.log('Opening');
sock.send('Marco!');
};
console.log('Received Message: ', e.data);
setTimeout(function() {
sayMarco()
}, 2000);
};
console.log('Closing');
};
function sayMarco() {
console.log('Sending Marco!');
sock.send('Marco!');
}
部署后打开浏览器运⾏,直接报 404 错误
上⽹搜索了⼀晚上解决⽅案,包括参考 stackoverflow 上的经验都未解决该问题,直到查看到以下⽂章:
在此⾃⼰也做个记录避免以后遗忘。
WebSocket 实质上借⽤ HTTP 请求进⾏握⼿,启⽤ Spring WebSocket 需要在 org.springframework.web.servlet.DispatcherServlet ⾥配置拦截此请求。
以下是解决步骤:
⾸先,修改 WebSocketConfig 类定义,在类上添加 @Configuration 注解,表明该类以 JavaConfig 形式⽤作 bean 定义的源(相当于 XML 配置中的 <beans> 元素)。import t.annotation.Bean;
import t.annotation.Configuration;
import org.springframework.fig.annotation.EnableWebSocket;
import org.springframework.fig.annotation.WebSocketConfigurer;
import org.springframework.fig.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 个⽅法:- 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[] {"/"};
}
}
重新部署后代开浏览器运⾏成功
客户端消息
服务器消息
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论