项目实战--网页五子棋(匹配模块)(4)

上期我们完成了游戏大厅的前端部分内容,今天我们实现后端部分内容

1. 维护在线用户

在用户登录成功后,我们可以维护好用户的websocket会话,把用户表示为在线状态,方便获取到用户的websocket会话

java 复制代码
package org.ting.j20250110_gobang.game;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import java.util.HashMap;
import java.util.Map;

@Component
public class OnlineUserManager {
    //使用ConcurrentHashMap保证线程安全
    private Map<Integer, WebSocketSession> onlineUser = new ConcurrentHashMap<>();

    public void enterGameHall(int userId, WebSocketSession session) {
        //用户上线
        onlineUser.put(userId, session);
    }

    public void exitGameHall(int userId) {
        //用户下线
        onlineUser.remove(userId);
    }

    public WebSocketSession getFromHall(int userId) {
        //获取用户的websocket会话
        return onlineUser.get(userId);
    }
}

这里我们借助一个哈希表就可以实现。

2. 实现webSocket相关方法

上期我们定义了webSocket的处理类,但是并没有完成重写的方法,接下来我们借助维护的在线用户具体实现如下方法

在实现这些方法之前,我们还需要按照上期约定好的信息交互形式定义两个实体类,代表请求和响应:

java 复制代码
package org.ting.j20250110_gobang.game;

public class MatchRequest {
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
java 复制代码
package org.ting.j20250110_gobang.game;

public class MatchResponse {
    private boolean ok;
    private String errMsg;
    private String message;

    public boolean isOk() {
        return ok;
    }

    public void setOk(boolean ok) {
        this.ok = ok;
    }

    public String getErrMsg() {
        return errMsg;
    }

    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

2.1 连接成功

java 复制代码
//连接成功后执行
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //玩家上线
        try {
            //获取登录时储存在session中的用户信息,这里WebSocketSession在注册时通过拦截器获取到了session中的内容
            User user = (User)session.getAttributes().get("user");
            if(onlineUser.getFromHall(user.getId()) == null) {
                onlineUser.enterGameHall(user.getId(), session);
                System.out.println("用户:" + user.getUsername() + " 已上线");
            }else{
                //防止重复登录
                MatchResponse response = new MatchResponse();
                response.setOk(false);
                response.setErrMsg("用户已在别处登录");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                session.close();
            }

        }catch (NullPointerException e) {
            e.printStackTrace();
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setErrMsg("用户未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }

    }

2.2 连接断开

java 复制代码
    //连接异常时执行
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        //连接异常断开,玩家下线
        try {
            User user = (User)session.getAttributes().get("user");
            //防止重复登录时删除正常登录的在线信息
            if(onlineUser.getFromHall(user.getId()).equals(session)) {
                onlineUser.exitGameHall(user.getId());
                System.out.println("用户:" + user.getUsername() + " 已下线");
            }
        }catch (NullPointerException e) {
            e.printStackTrace();
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setErrMsg("用户未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
    }
    //连接正常断开后执行
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        //连接正常断开,玩家下线
        try {
            User user = (User)session.getAttributes().get("user");

            //防止重复登录时删除正常登录的在线信息
            if(onlineUser.getFromHall(user.getId()).equals(session)) {
                onlineUser.exitGameHall(user.getId());
                System.out.println("用户:" + user.getUsername() + " 已下线");
            }

        }catch (NullPointerException e) {
            e.printStackTrace();
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setErrMsg("用户未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
    }

2.3 处理匹配请求

java 复制代码
    //接收到请求后执行
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        User user = (User) session.getAttributes().get("user");
        MatchRequest request = objectMapper.readValue(message.getPayload(), MatchRequest.class);
        MatchResponse response = new MatchResponse();
        if(request.getMessage().equals("startMatch")) {
            //开始匹配,把用户加入匹配队列
            //todo
            response.setOk(true);
            response.setMessage("startMatch");
        }else if(request.getMessage().equals("stopMatch")) {
            //取消匹配,从匹配队列中移除用户
            //todo
            response.setOk(true);
            response.setMessage("stopMatch");
        }else{
            response.setOk(false);
            response.setErrMsg("非法请求");
        }
    }

这里=具体的匹配队列功能我们下期再实现

相关推荐
weixin_7275356213 小时前
MinIO大文件上传深度拆解:从原理到生产落地的完整指南
java·中间件
摇滚侠14 小时前
Java 全栈开发实战教程 课程笔记 34-36
java·笔记
芝士熊爱编程14 小时前
创建型模式-单例模式
java·单例模式·设计模式
大模型码小白14 小时前
Spring AI 框架实战:Java 后端集成大模型的架构设计与工程落地
java·人工智能·python·spring
weixin_BYSJ198714 小时前
「课设设计」springboot校园超市助购系统26449 (附源码)
java·javascript·spring boot·python·django·flask·php
栋***t15 小时前
从“纸质试卷”到“AI智能组卷”,麦塔在线考试系统如何重构出题逻辑?
java·大数据·人工智能·算法·重构
CHANG_THE_WORLD15 小时前
深入理解递归:从函数调用到调用栈的完整执行过程
java·开发语言·算法
xexpertS15 小时前
CI/CD 熔断机制:如何通过编排级熔断器提升开发者效率
java·linux·运维
zy happy15 小时前
VMware虚拟机添加新的硬盘
java·linux·jvm·docker
AI人工智能+电脑小能手16 小时前
【大白话说Java面试题 第192题】【08_Kafka篇】第8题:死信队列是什么?延时队列是什么?
java·kafka·消息队列·死信队列·延时队列