应用场景:
WebSocket 是 HTML5 提供的在单个 TCP 链接上进行全双工通讯的协议。
客户端请求
Request URL: ws://127.0.0.1:8080/webSocket/88274.2421418903
Request Method: GET
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: Uzqa3dqq8zeBv2Ol4nxOaQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
服务端响应
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: Fl7B8k4erUi8bempzvN91WtKtqk=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
WebSocket 的属性
WebSocket 的事件
WebSocket 的方法
使用
// 创建链接
var ws = new WebSocket(url, [protocol] );
// 建立连接后的回调函数
ws.onopen = function (event) {
};
// 收到服务端消息的回调函数
ws.onmessage = function (event) {
};
// 通信错误的回调函数
ws.onerror = function (event) {
};
// 连接关闭的回调函数
ws.onclose = function (event) {
}
// 发送数据
function send() {
ws.send(JSON.stringify(message));
}
// 关闭连接
function closeWebSocket() {
ws.close();
}
Failed to construct ‘WebSocket’: The URL’s scheme must be either ‘ws’ or ‘wss’. ‘localhost’ is not allowed.
url 协议不要忽略 ws
或 wss
分别对应 http
与 https
的区别
index.html 文件放置位置 resource/static/index.html
直接访问地址:localhost:8080/index.html
springboot 在 resource 文件夹下有两个默认文件夹
添加 spring-boot-starter-websocket 依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-websocketartifactId>
dependency>
定义监听端点,和监听事件(与前端的监听事件相同)
@ServerEndpoint("/webSocket/{sid}")
@Component
public class WebSocketServer {
// 事件
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {}
@OnMessage
public void onMessage(Session session, String message) {}
@OnError
public void onError(Session session, Throwable error) {}
@OnClose
public void onClose() {}
// 方法
private Session session; // 客户端连接对象
public void fun(){
// 发送消息
this.session.getBasicRemote().sendText(message);
// 关闭连接
this.session.close();
}
}
index.html:22 WebSocket connection to ‘ws://127.0.0.1:8080/webSocket/10000’ failed: Error during WebSocket handshake: Unexpected response code: 404
在使用 springboot 内置的 Tomcat 容器时,需要注入 ServerEndpointExporter,这个 bean 中的 registerEndpoints() 方法会将 @ServerEndpoint 注解的 bean 添加到 serverContainer 容器中。
ServerEndpointExporter 是由 spring-boot-starter-websocket 提供的,并且这个项目的子项目中包含 starter-web,所以单独做一个 websocket 时只需要依赖 starter-websocket 即可
@Configuration
public class WebSocketConfig {
/**
* 使用内置 tomcat 需要定义 bean
* 外置则不需要,否则会报错
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
如果还是失败,需要检查是否将这个类注册为 bean。需要添加 @Component 注解,@ServerEndpoint 不会生成一个 bean,它是 Tomcat 中的注解,表示服务监听端点的地址。
@ServerEndpoint("/webSocket/{sid}")
@Component
public class WebSocketServer {}
因为 ServerEndpointExporter 注册时是从所有 bean 中查找
protected void registerEndpoints() {
String[] endpointBeanNames = context.getBeanNamesForAnnotation(ServerEndpoint.class);
}
连接错误 导致 连接断开
在服务端的 onMessage 方法中抛出未捕获异常会触发 onError 事件,然后触发 onClose 事件。最终也会触发客户端的 onClose 事件。
客户端 onMessage 方法中异常不会触发其它监听事件。
码云:源码参考传送门
参考: