一、简介
参考 : https://www.runoob.com/html/html5-websocket.html
二、原理
简言之 , ws即通过 “tcp一次握手” 建立连接 , 连接升级连接为websocket, 后续不再需要复杂的请求头 和 三次握手四次分手。建立连接后数据以帧数值传递,并携带base64密钥双向验证,不匹配的话 立即断开连接。
三、原生语法
1、创建对象
var Socket = new WebSocket(url, [protocol] );
2、属性
Socket.readyState
Socket.bufferedAmount
3、事件
Socket.onopen
Socket.onmessage
Socket.onerror
Socket.onclose
4、方法
Socket.send()
Socket.close()
注:ws虽然语法简单清晰, 但是目前有些浏览器不支持websocket,为了解决兼容性问题需要回退为ajax轮询方式, 这时需要使用 sockjs : https://github.com/sockjs/sockjs-client
即使连接建立后,传递消息格式也需要协议规范 ,我们需要引入 stomp 协议。保证服务器和客户端的双端协议建立在tcp协议之上。
可以使用的方法 :
SEND 发送
SUBSCRIBE 订阅
UNSUBSCRIBE 退订
BEGIN 开始
COMMIT 提交
ABORT 取消
ACK 确认
DISCONNECT 断开
四、demo : 多人聊天室
思路 : 由前端建立连接,后台收到消息send给代理,由代理广播到一个接口,client 订阅这个代理接口,接收消息。
1 、创建项目、添加依赖:
创建项目时,添加web 、 websocket ,再利用https://mvnrepository.com 添加 webjars 中其他依赖。
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>stomp-websocket</artifactId>
<version>2.3.3-1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
注 :由于没引入数据库,“群组区分”仅仅在前端展示, 后台消息广播就不做处理了。
2、前端代码 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>聊天室</title>
<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/sockjs-client/sockjs.min.js"></script>
<script src="/webjars/stomp-websocket/stomp.min.js "></script>
<!--<script src="js/chat.js"></script>-->
</head>
<body>
<table>
<tr>
<td>请输入用户名</td>
<td><input type="text" id="name"></td>
<td>请输入房间号</td>
<td><input type="text" id="group"></td>
</tr>
<tr>
<td>连接</td>
<td><input type="button" id="connect" value="connect"></td>
<td>登出</td>
<td><input type="button" id="disconnect" disabled="disabled" value="disconnect"></td>
</tr>
</table>
<div id="chat" style="display: none">
<table>
<tr>
<td>
<input type="text" id="content" placeholder="请输入聊天内容">
</td>
<td>
<input type="button" id="send" value="发送">
</td>
</tr>
</table>
</div>
<div id="conversation">群聊进行中</div>
<script>
var stompClient = null;
var chatRoom = "";
$(function(){
$("#connect").click(function () {
connect();
chatRoom = $("#group").val();
});
$("#disconnect").click(function () {
if (stompClient != null){
stompClient.disconnect();
}
setConnected(false);
});
$("#send").click(function () {
stompClient.send("/app/chat",{},JSON.stringify({ // 接口 , 权限 , 数据
"name": $("#name").val(),
"content":$("#content").val(),
"group":$("#group").val()
}));
});
})
function connect() {
if (!$("#name").val() || !$("#group").val()){
return;
}
let ws = new SockJS('/chat'); //连接点
stompClient = Stomp.over(ws);
stompClient.connect({},function (success) {//权限 , success 回调 , fail 回调
setConnected(true);
stompClient.subscribe('/topic/greetings',function (msg) {
if (JSON.parse(msg.body).group == chatRoom) {
showGreeting(JSON.parse(msg.body));
}
})
});
}
function showGreeting(msg) {
$("#conversation").append('<div>' + msg.group + ':' + msg.name + ':' + msg.content + '</div>');
}
function setConnected(flag) {
// set buttons status
$("#connect").prop("disabled",flag);
$("#disconnect").prop("disabled",!flag);
if (flag) {
$("#chat").show()
}
}
</script>
</body>
</html>
3、后台代码 :
config :
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic"); //广播代理 , subscribe
registry.setApplicationDestinationPrefixes("/app"); // 代理拦截的消息 mapping 前缀
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();//连接点
}
}
controller :
@Controller
public class ChatController {
@MessageMapping("/chat")
@SendTo("/topic/greetings")
public Message chatting(Message message){
return message;
}
}
参考 : www.javaboy.org
网友评论