使用spring boot 搭建WebSocket
WebSocket
-
什么是WebSocket:
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
普通http协议有一个严重的缺陷,通信只能有客户端发起.假如服务端有了连续的变化,客户端如果想获知,只能用轮询来获取.但轮询的效率低,非常浪费资源,这时WebSocket就此诞生了.
WebSocket 于2008年诞生,2011年成为国际标准。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种.
其他特点包括:
1. 建立在 TCP 协议之上,服务器端的实现比较容易
2. 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议
3. 数据格式比较轻量,性能开销小,通信高效
4. 可以发送文本,也可以发送二进制数据
5. 没有同源限制,客户端可以与任意服务器通信
6. 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL
下面简单介绍一下spring boot下如何整合WebSocket
这里使用tio框架进行WebSocket服务的搭建
plugins {
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.t-io:tio-websocket-spring-boot-starter:3.6.0.v20200315-RELEASE'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
引入tio-websocket-spring-boot-starter依赖
构建服务端
-
给SpringBoot Application 主类添加 @EnableTioServerServer 注解
@SpringBootApplication @EnableTioWebSocketServer public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
-
修改配置文件
tio: websocket: server: port: 9998 # 心跳时间 heartbeat-timeout: 60000
-
创建消息处理类
@Configuration public class MyWebSocketMsgHandler implements IWsMsgHandler { /** * 握手时走这个方法,业务可以在这里获取cookie,request参数等 */ @Override public HttpResponse handshake(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception { return httpResponse; } /** * 握手成功后触发该方法 */ @Override public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception { System.out.println("握手成功"); } /** * 当ws是基于BINARY(字节)传输的,会执行此方法 */ @Override public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception { System.out.println("接收到bytes消息"); return null; } /** * 当客户端发close flag时,会走这个方法 */ @Override public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception { return null; } /** * 当ws是基于TEXT传输的,就会走到这个方法 */ @Override public Object onText(WsRequest wsRequest, String s, ChannelContext channelContext) throws Exception { System.out.println("接收到文本消息:"+s); return fakeAi(s); } private String fakeAi(String input){ if (input == null || "".equals(input)) { return "你说什么?没听清︎"; } return input.replace('你', '我') .replace("吗", "") .replace('?', '!') .replace('?', '!'); } }
-
构建客户端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket客户端</title>
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<style>
.jumbotron {
width: 100%;
}
#text {
height: 3rem;
font-size: 1rem;
line-height: 3rem;
margin: 1rem;
}
.btn {
margin-right: 5px;
}
#connect {
margin-left: 1rem;
}
#log {
margin: 1rem 0 0 1rem;
}
</style>
<div class="container">
<div class="row">
<div class="jumbotron">
<input type="text" placeholder="请输入你想传输的内容" id="text" class="col-lg-12" />
<input type="button" value="连接" class="btn btn-info" id="connect" onclick="connect()" />
<input type="button" value="发送" class="btn btn-success" id="sent" disabled="disabled"
onclick="sent()" />
<input type="button" value="断开" class="btn btn-danger" id="disconnect" disabled="disabled"
onclick="disconnect()" />
<div id="log">
<p>聊天记录:</p>
</div>
</div>
</div>
</div>
<script type="text/javascript">
let text = document.querySelector('#text');
let connectBtn = document.querySelector("#connect");
let sentBtn = document.querySelector("#sent");
let disconnectBtn = document.querySelector("#disconnect");
let logDiv = document.querySelector("#log");
let ws = null;
function connect() {
ws = new WebSocket("ws://localhost:9998/test");
ws.onopen = function () {
setConnected(true);
log('和服务端连接成功!');
};
ws.onmessage = function (event) {
log('服务端说:' + event.data);
};
ws.onclose = function () {
setConnected(false);
log('和服务端断开连接!')
}
}
function sent() {
if (ws != null) {
ws.send(text.value);
log('客户端说:' + text.value);
} else {
log('请先建立连接!')
}
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
setConnected(false);
}
function log(value) {
let content = document.createElement('p');
content.innerHTML = value;
logDiv.appendChild(content);
text.value = '';
}
function setConnected(connected) {
connectBtn.disabled = connected;
disconnectBtn.disabled = !connected;
sentBtn.disabled = !connected;
}
</script>
</body>
</html>
运行效果
使用spring boot 搭建WebSocket
https://guiyunweb.com/archives/%E4%BD%BF%E7%94%A8springboot%E6%90%AD%E5%BB%BAwebsocket