我给你做一套开箱即用、可直接运行的 Java WebSocket 代码,包含:
后端(SpringBoot + WebSocket)
前端(原生 HTML/JS)
一对一聊天、广播消息、连接状态提示
无任何复杂配置,复制就能跑
一、后端实现(SpringBoot)
- 先加 Maven 依赖(pom.xml)
> <!-- SpringBoot Web 核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- WebSocket 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
- WebSocket 配置类
开启 WebSocket 支持
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* WebSocket 配置类
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
WebSocket 服务核心类(真正处理连接 / 消息)
java
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* WebSocket 服务端
* ws://localhost:8080/ws/用户名
*/
@Component
@ServerEndpoint("/ws/{userId}")
public class WebSocketServer {
// 静态变量,记录当前在线连接数(线程安全)
private static int onlineCount = 0;
// 线程安全 Set,存放每个客户端对应的 WebSocket 对象
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
// 线程安全 Map,存放用户ID与Session对应关系
private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();
// 与客户端的会话Session,需要通过它给客户端发送数据
private Session session;
private String userId;
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) {
this.session = session;
this.userId = userId;
sessionMap.put(userId, session);
webSocketSet.add(this);
addOnlineCount();
System.out.println("用户【" + userId + "】连接成功!当前在线人数:" + getOnlineCount());
sendMessage("连接WebSocket服务端成功!你的ID:" + userId);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this);
sessionMap.remove(userId);
subOnlineCount();
System.out.println("用户【" + userId + "】退出连接!当前在线人数:" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("收到用户【" + userId + "】消息:" + message);
// 消息格式:toUserId:内容
// 例:123:你好
try {
if (message.contains(":")) {
String[] split = message.split(":", 2);
String toUserId = split[0];
String content = split[1];
sendToUser(userId, toUserId, content);
} else {
// 无指定用户 → 广播给所有人
sendToAll("【" + userId + "】说:" + message);
}
} catch (Exception e) {
sendMessage("消息格式错误!正确格式:目标用户ID:消息内容");
}
}
/**
* 发生错误时调用
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("WebSocket 发生错误");
error.printStackTrace();
}
// ==================== 发送消息工具方法 ====================
/**
* 发送消息给当前用户
*/
public void sendMessage(String message) {
this.session.getAsyncRemote().sendText(message);
}
/**
* 点对点发送消息
*/
public void sendToUser(String fromUserId, String toUserId, String message) {
Session session = sessionMap.get(toUserId);
if (session != null && session.isOpen()) {
session.getAsyncRemote().sendText("【" + fromUserId + "】私聊你:" + message);
} else {
this.sendMessage("用户【" + toUserId + "】不在线!");
}
}
/**
* 广播消息(所有人)
*/
public static void sendToAll(String message) {
for (WebSocketServer webSocket : webSocketSet) {
webSocket.session.getAsyncRemote().sendText(message);
}
}
// ==================== 在线人数统计 ====================
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
前端实现(HTML + 原生 JS)
新建一个 ws.html 文件,直接双击打开就能用,无需部署到服务器。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>WebSocket 聊天</title>
<style>
body { max-width: 800px; margin: 20px auto; }
#msgBox { height: 400px; border: 1px solid #ccc; padding: 10px; overflow-y: auto; margin-bottom: 10px; }
#message { width: 70%; padding: 8px; }
button { padding: 8px 16px; cursor: pointer; }
</style>
</head>
<body>
<h3>WebSocket 在线聊天</h3>
<div>
请输入你的ID:<input type="text" id="userId" placeholder="例如:1001">
<button onclick="connect()">连接服务端</button>
<button onclick="closeConnect()">断开连接</button>
</div>
<br>
<div id="msgBox"></div>
<div>
<input type="text" id="message" placeholder="发送消息,格式:目标ID:内容(直接输入则广播)">
<button onclick="sendMsg()">发送</button>
</div>
<script>
let ws;
const msgBox = document.getElementById('msgBox');
// 连接 WebSocket
function connect() {
const userId = document.getElementById('userId').value.trim();
if (!userId) {
alert("请输入用户ID!");
return;
}
// 如果已连接,先关闭
if (ws && ws.readyState !== WebSocket.CLOSED) {
ws.close();
}
// 创建 WebSocket 连接
ws = new WebSocket("ws://localhost:8080/ws/" + userId);
// 连接成功
ws.onopen = function () {
addMsg("系统", "连接服务端成功!");
};
// 收到服务端消息
ws.onmessage = function (event) {
addMsg("服务端", event.data);
};
// 连接关闭
ws.onclose = function () {
addMsg("系统", "已断开连接!");
};
// 连接错误
ws.onerror = function () {
addMsg("系统", "连接失败!请检查服务端是否启动");
};
}
// 发送消息
function sendMsg() {
const msg = document.getElementById('message').value.trim();
if (!msg || !ws || ws.readyState !== WebSocket.OPEN) {
alert("未连接或消息为空!");
return;
}
ws.send(msg);
addMsg("我", msg);
document.getElementById('message').value = "";
}
// 断开连接
function closeConnect() {
if (ws) {
ws.close();
}
}
// 追加消息到页面
function addMsg(user, text) {
const div = document.createElement('div');
div.style.margin = "5px 0";
div.innerHTML = "<strong>" + user + "</strong>:" + text;
msgBox.appendChild(div);
// 滚动到底部
msgBox.scrollTop = msgBox.scrollHeight;
}
</script>
</body>
</html>
核心功能说明
- 在线人数统计
- 点对点私聊
- 全局广播
- 连接状态实时提示
- 线程安全,支持高并发
- 前后端完全分离