目录
前言
一、分析
1.1、qq聊天功能分析
1.2、WebSocket介绍
1.2.1、什么是消息推送呢?
1.2.2、原理解析
1.2.3、报文格式
二、简易demo
2.1、后端实现
2.1.1、引入依赖
2.1.2、继承TextWebSocketHandler
2.1.3、实现 WebSocketConfigurer 接口
2.2、前端实现
2.3、执行效果
基于 WebSocket、Spring Boot 下,用一个简易的小 demo 讲解一下“QQ聊天”功能原理~
用户看到的实际效果:用户A 给用户B 发送了一条消息,用户B在聊天框看到了消息,接着用户B回复消息......
底层实现:主机A 给服务器发送了一个 HTTP 请求,这个请求中就包含了用户A 要给用户B 发送的消息,服务器将收到的请求进行解析,在将响应发送给 主机B,这个响应中就包含了用户A 要发送的消息~
对于以上场景,我们应该如何实现呢?接着往下看!
WebSocket 是从 HTML5 开始支持的一种网页端和服务端保持长连接的 消息推送机制。
传统的 web 程序都是 “一问一答” 的形式,客户端给服务器发送了个 HTTP 请求,服务器根据请求计算响应返回客户端。显然,这种传统的 web 程序如果客户端不主动发起请求,服务器就无法主动给客户端发送响应~
Ps:若想使用原生的 HTTP 协议实现消息推送,需要进行“轮询”,反复询问服务器是否收到请求,成本太高
而 WebSocket 则是更接近 TCP 这种级别的通信方式——一旦连接建立完成,客户端或服务器都可以主动向对方发送数据。
WebSocket 协议本质上是基于 TCP 协议的,为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,通过这个附加头信息完成握手过程~
Spring 中内置了 websocket ,可以直接进行使用,如何使用?往下看~
创建一个 Spring Boot 项目,接着我们需要引入 Spring Web 依赖,以及 Web Socket 依赖。
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-websocket
这里我们先创建一个类,自定义名为 TestAPI ,继承 TextWebSocketHandler 类,重写这个类下4个最关键的方法:
这个类就是用来处理 WebSocket 相关请求的~
于是,我们就可这样写:
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
@Component
public class TestAPI extends TextWebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("连接成功");
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("收到消息:" + message.getPayload());
//收到消息后向客户端反馈信息(这里反馈相同数据)
session.sendMessage(message);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
System.out.println("连接异常");
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("连接关闭");
}
}
第一步,创建一个类,自定义类名为WebSocketConfig,实现 WebSocketConfigurer接口,这个接口下只需要实现一个方法 registerWebSocketHandlers,这个类就是用来注册添加 WebSocket (当前项目要添加的就是我们刚刚写的 TestAPI 这个类)以及注册路由(这个路由就将客户端与服务器联系起来了:前端创建 WebSocket 实例时,就需要写下对应的路由)。
第二步、注入 TestAPI 类,最后使用 addHander方法添加注册这个类,基于这个类才能进一步的找到 TestAPI 这个类,去处理 WebSocket相关的请求~
代码实现如下:
import com.example.demo.api.TestAPI;
import org.springframework.beans.factory.annotation.Autowired;
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 //启动 WebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private TestAPI testAPI;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry.addHandler(testAPI, "/test");
}
}
Ps:
@EnableWebSocket
注解是用来让 Spring 框架认识这个类是用来配置 webSocket 的类,基于这个类才能进一步的找到 TestAPI 这个类,去处理 WebSocket相关的请求~
前端需要创建 WebSocket 实例,并写下相应路由,这个路由就是与后端 webSocket 相对应的那个路由,如下:
接着前端也可以通过 WebSocket 的4个重要方法,根据响应打印对应日志:
最后通过按钮输入框的形式来发送相应的 HTTP 请求,代码如下:
Document
启动程序,输入对应URL,如下结果;
发送消息,点击按钮(相当于主机A 给主机B 发送消息,这里实现的是一个简易版,是一个回显服务),如下结果:
最后关闭浏览器,断开连接:
这样一个简单 demo 就完成了~