赞
踩
WebSocket connection to ‘ws://localhost:8080/bidingRecord’ failed: Error during WebSocket handshake: Unexpected response code: 200
翻译:WebSocket握手过程中出错:意外响应代码:200
代码实现
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.dtdream</groupId> <artifactId>web-socket</artifactId> <version>0.0.1-SNAPSHOT</version> <name>web-socket</name> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>5.0.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
code
1、注入ServerEndpointExporter(使用SpringBoot时使用?)
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * @desc: * @author: admin * @date: 2020/06/02 **/ @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
2、WebSocket连接服务
import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; /** * @desc: WebSocket服务 * @author: admin * @date: 2020/06/02 **/ @Component @ServerEndpoint("/bidingRecord") @Slf4j public class WebSocket { private Session session; private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>(); /** * 建立连接 * @param session */ @OnOpen public void onOpen(Session session) { this.session = session; webSockets.add(this); log.info("【新建连接】,连接总数:{}", webSockets.size()); } /** * 断开连接 */ @OnClose public void onClose(){ webSockets.remove(this); log.info("【断开连接】,连接总数:{}", webSockets.size()); } /** * 接收到信息 * @param message */ @OnMessage public void onMessage(String message){ log.info("【收到】,客户端的信息:{},连接总数:{}", message, webSockets.size()); } /** * 发送消息 * @param message */ public void sendMessage(String message){ log.info("【广播发送】,信息:{},总连接数:{}", message, webSockets.size()); for (WebSocket webSocket : webSockets) { try { webSocket.session.getBasicRemote().sendText(message); } catch (IOException e) { log.info("【广播发送】,信息异常:{}", e.fillInStackTrace()); } } } }
以上代码写出来的demo,已可以实现WebSocket的连接,但是为什么会出现握手出错的问题呢?
解决思路
1、查阅网上的资料
以上代码写出来的demo是可以本地访问的,但是我把这些代码加到项目中就不好使了。网上的资料基本在说实现上的问题,尝试后跟资料中提供的一些信息也不一样,就没得到解决。
2、猜想原因
由于我们使用的是域名访问,我开始猜测是反向代理中没设置WebSocket连接的相关配置。结果问了下运维,运维说我们没用反向代理,尴尬了。
3、询问有经验的老师
整不出来,就问当初给我WebSocket的demo的老师,老师很有经验,让我原始代码给他,他也很快定位到了问题的位置,大概就在过滤器的位置,让后让我打点日志看看,具体什么原因。机智的我把这块过滤器代码拷贝到我的demo中,结果发现本地原本可以访问的WebSocket连接,现在也不好使了,而且报的是相同的错误。当时,真是第一次替Bug感到高兴,太好了,基本问题就定位在这个过滤器上了。
过滤器代码
import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @desc: * @author: admin * @date: 2020/06/02 **/ @Slf4j @Component class ApiFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; HttpServletResponse response = (HttpServletResponse)servletResponse; String requestURI = request.getRequestURI(); if(!requestURI.startsWith("/api") && !requestURI.equals("/index.html")) { request.getRequestDispatcher("/index.html").forward(request, response); }else { filterChain.doFilter(servletRequest,servletResponse); } } @Override public void destroy() { } }
看过上面代码你会发现,我的请求"/bidingRecord"会被转发走,而不会到达WebSocket的连接处。不信,你可以先加上这块过滤器的代码Debug一下,到这里会转发走,就会报上文中的错误。所以,问题就这样解决了,将WebSocket的请求URI配置上,不被转发走即可。
修改过的过滤器代码
import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @desc: * @author: admin * @date: 2020/06/02 **/ @Slf4j @Component class ApiFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; HttpServletResponse response = (HttpServletResponse)servletResponse; String requestURI = request.getRequestURI(); if(!requestURI.startsWith("/api") && !requestURI.equals("/index.html") // 配置WebSocket连接不被转发即可 && !requestURI.equals("/bidingRecord")) { request.getRequestDispatcher("/index.html").forward(request, response); }else { filterChain.doFilter(servletRequest,servletResponse); } } @Override public void destroy() { } }
总结
WebSocket连接未真正到达连接节点处,请求发出中间为什么没到到达连接的节点,是解决问题的关键。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。