【SpringBoot】使用WebSocket做消息对话
Http协议只能客户端发送---服务器回复,
无法做到服务器主动向客户端发送消息,所以可以使用websocket来进行双向通道 发消息
研究了一下抖音 斗鱼的弹幕也是用的websocket,但是需要解密ws内容
可以使用拦截websocket 接管websocket的方式截取弹幕,做一个弹幕回复之类 游戏或者主播感谢回复 牛批哄哄的
后端:
pom载入websocket依赖
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
Springboot需要写个配置类
注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
ws控制层各类事件处理和转发
package com.example.websocketdemo.websocket;
import cn.hutool.json.JSONObject;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@ServerEndpoint("/websocket/{name}")//开启websocket
@Component
public class WebSocket {
private String name;//建立用户
private Session session;//当前链接
private static Map<String,WebSocket> allClients = new HashMap<>();
// 用户连接事件
@OnOpen
public void onOpen(@PathParam("name")String name ,Session session){
System.out.println("连接建立:" + name);
this.name =name;
this.session = session;
// 存入链接用户名字和session
allClients.put(name,this);
}
// 接收消息事件
@OnMessage
public void onMessage(Session session,String message){
System.out.println(message);
System.out.println("接收消息事件");
String to = new JSONObject(message).getStr("toUser");//获取目标接收者
String toMessage =new JSONObject(message).getStr("toMessage");//获取发送的内容
WebSocket webSocket = allClients.get(to);//获取目标接收者websocket
// 判断目标接收者是否为空
if (webSocket !=null){
Session tosession = webSocket.getSession();//获取接收方session
// 若链接是打开状态
if (tosession.isOpen()){
tosession.getAsyncRemote().sendText(toMessage);//找到链接的另外一端然后发消息
}
}else {
session.getAsyncRemote().sendText("对方不在线");
}
}
// 关闭连接事件
@OnClose
public void OnClose(){
System.out.println("关闭连接事件");
allClients.remove(this.name);//清除掉已退出的用户
}
// 出现异常事件
@OnError
public void onError(Throwable e){
System.out.println("出现异常事件");
}
public String getName() {
return name;
}
public Session getSession() {
return session;
}
public static Map<String, WebSocket> getAllClients() {
Set<String> strings = allClients.keySet();
for (String string : strings) {
}
return allClients;
}
// 获取所有key
public static ArrayList<String> getKey(){
ArrayList<String> strings = new ArrayList<>();
Set<String> keys = allClients.keySet();
for (String string : keys) {
strings.add(string);
}
return strings;
}
}
前端:
一个简单的连接和对话页面,直接静态打开就能run
判断浏览器有没有WebSocket环境(一般都自带了 没有就是浏览器太垃圾 直接换)
需要注册一个WebSocket对象,和后端一样有各类事件触发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
function start() {
alert(document.location.host)
}
var websocket = null;
function connection() {
var username = document.getElementById("name").value;
if ('WebSocket' in window) {
websocket = new WebSocket('ws://127.0.0.1:8080/websocket/' + username);
} else {
alert("当前浏览器没有WebSocket环境")
}
websocket.onopen = function () {
document.getElementById("message").innerHTML = "链接已建立"
};
websocket.onmessage = function (event) {
var data = event.data;
document.getElementById("message").innerHTML = data;
};
websocket.onerror = function () {
document.getElementById("message").innerHTML = "出现异常"
};
websocket.onclose = function () {
document.getElementById("message").innerHTML = "链接已关闭"
};
// 监听窗口关闭事件
window.onbeforeunload = function () {
if (websocket != null) {
websocket.close()
}
}
}
// 发送
function sendMessage() {
var toUser = document.getElementById("toUser").value;
var toMessage = document.getElementById("toMessage").value;
if (websocket != null) {
var message = '{"toUser":"' + toUser + '","toMessage":"' + toMessage + '"}';
websocket.send(message);
}
}
</script>
</head>
<body>
<input type="text" id="name">
<button onclick="connection()">链接</button><br>
接收者:<input type="text" id="toUser"><br>
内容:<input type="text" id="toMessage"><br>
<button onclick="sendMessage()">发送</button>
<span id="message"></span>
</body>
</html>