最近在学习webSocket这一块内容。先是做了个简单的聊天室,然后就遇到问题了。
@ServerEndpoint("/hall/{nickName}")
@Component
public class Hall {
//当前在线人数
private static int onlineCount = 0;
//每个客户端对应的session
private static ConcurrentHashMap<String,Session> webSocketMap = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session, @PathParam("nickName")String nickName) throws IOException {
if (webSocketMap.containsKey(nickName)){
sendMessage(webSocketMap.get(nickName),"已在其他地方登录");
onClose(nickName);
webSocketMap.put(nickName,session);
}else {
webSocketMap.put(nickName,session);
onlineCount++;
sendToAll(nickName+"进入大厅");
* 连接关闭调用的方法
@OnClose
public void onClose(@PathParam("nickName")String nickName){
if (webSocketMap.containsKey(nickName)) {
webSocketMap.remove(nickName);
onlineCount--;
sendToAll(nickName+"离开了大厅");
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
@OnMessage
public void onMessage(@PathParam("nickName")String nickName,String message) {
//群发消息
for(Session session: webSocketMap.values()){
try {
message = nickName+":"+message;
sendMessage(session,message);
} catch (IOException e) {
e.printStackTrace();
continue;
public void sendMessage(Session session,String message) throws IOException {
session.getBasicRemote().sendText(message);
public void sendToAll(String message){
//群发消息
for(Session session: webSocketMap.values()){
try {
sendMessage(session,message);
} catch (IOException e) {
e.printStackTrace();
continue;
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
var websocket = null;
var nickName = document.getElementById('nickName').innerHTML;
window.onload = () => {
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/hall/" + nickName);
} else {
alert('当前浏览器不支持websocket')
//连接成功建立的回调方法
websocket.onopen = function () {
// showMessage("<span style='color: green'>连接成功!</span><br/>");
//发生了错误事件
websocket.onerror = function() {
showMessage("<span style='color:red'>与服务器连接发生错误</span>");
//获得消息
websocket.onmessage = function (message) {
showMessage(message.data);
//关闭事件
websocket.onclose = function () {
showMessage("与服务器连接已断开");
//显示信息
function showMessage(message) {
let messageBox = document.getElementById('messageBox');
messageBox.innerHTML += message+"<br/>" ;
send.onclick = () => {
let message = document.getElementById('message');
websocket.send(message.value);
message.value = "";
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
websocket.close();
以上是服务端和客户端的代码。
当我在测试同一用户名在异地登录的时候,确实服务端不会再给原来的浏览器发送任何消息了。但是原来的浏览器还能给服务端发送消息啊。
所以我在想,服务端如何发起断开连接请求,告诉客户端,去断开连接
服务端主动断开客户端链接的时候,可以给两个参数,一个是code,一个是reason。表示状态码和断开的原因。
void close(CloseReason closeReason) throws IOException;
public CloseReason(CloseReason.CloseCode closeCode, String reasonPhrase);
客户端可以监听到这个 onclose事件,并且从event对象中获取到这两个属性。
websocket.onclose(event) => {
const code = event.code;
const reason = event.reason;