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

news/2025/2/24 17:50:33

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

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("非法请求");
        }
    }

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


http://www.niftyadmin.cn/n/5864672.html

相关文章

【Java 面试 八股文】JVM 虚拟机篇

JVM 虚拟机篇 1. JVM组成1.1 JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f;1.2 什么是程序计数器&#xff1f;1.3 你能给我详细的介绍Java堆吗?1.4 Java 虚拟机栈1.4.1 Java Virtual machine Stacks (java 虚拟机栈)1.4.2 栈和堆的区别1.4.3 垃圾回收是否涉及栈内…

2024华为OD机试真题-水仙花数Ⅰ(C++)-E卷B卷-100分

2024华为OD机试最新题库-(C卷+D卷+E卷)-(JAVA、Python、C++) 目录 题目描述 输入描述 输出描述 用例1 用例2 解题思路 考点 代码 c++ 题目描述 所谓水仙花数,是指一个n位的正整数,其各位数字的n次方和等于该数本身。 例如153是水仙花数,153是一个3位数,并且153…

uni-app 系统学习,从入门到实战(一)—— 从零开始搭建第一个跨平台应用

全篇大概 1500 字&#xff0c;建议阅读时间 5min 简介 UniApp 是一个基于 Vue.js 的跨平台开发框架&#xff0c;开发者可以通过编写一套代码&#xff0c;同时发布到 iOS、Android、H5、微信小程序、支付宝小程序、百度小程序等多个平台。本文将带你从零开始&#xff0…

Docker内存芭蕾:优雅调整容器内存的极限艺术

title: “&#x1f4be; Docker内存芭蕾&#xff1a;优雅调整容器内存的极限艺术” author: “Cjs” date: “2025-2-23” emoji: “&#x1fa70;&#x1f4a5;&#x1f4ca;” 当你的容器变成内存吸血鬼时… &#x1f680; 完美内存编排示范 &#x1f4dc; 智能内存管家脚本…

c语言 枚举用法技巧

c语言 枚举用法技巧 typedef enum {Red 0,Green } sc4336p_res_mode;int i 0; td_u8 image_mode;image_mode (sc4336p_res_mode)i; 此分析摘自chatgpt 在你提供的 C 代码片段中&#xff0c;你尝试将一个整数值 i 转换为 sc4336p_res_mode 枚举类型&#xff0c;并将其赋值给…

Sublime Text4安装、汉化

-------------2025-02-22可用---------------------- 官方网址下载&#xff1a;https://www.sublimetext.com 打开https://hexed.it 点击打开文件找到软件安装目录下的 ctrlf 查找 8079 0500 0f94 c2右边启用替换替换为:c641 0501 b200 90点击替换按钮 替换完成后 另存为本地…

车载DoIP协议 --- TCP详细解析

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 简单&#xff0c;单纯&#xff0c;喜欢独处&#xff0c;独来独往&#xff0c;不易合同频过着接地气的生活…

数据结构与算法再探(七)查找-排序

查找 一、二分查找 二分查找是一种高效的查找算法&#xff0c;适用于在已排序的数组或列表中查找特定元素。它通过将搜索范围逐步减半来快速定位目标元素。理解二分查找的“不变量”和选择左开右闭区间的方式是掌握这个算法的关键。 二分查找关键点 不变量 在二分查找中&a…