项目实战--网页五子棋(游戏大厅)(3)

我们的游戏大厅界面主要需要包含两个功能,一是显示用户信息,二是匹配游戏按钮

1. 页面实现

hall.html

html 复制代码
<!DOCTYPE html>
<html lang="ch">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>游戏大厅</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/hall.css">
</head>
<body>
    <div class="nav">五子棋</div>
    <div class="container">
        <div class="dialog">
            <!-- 展示用户信息 -->
            <div id="screen"></div>
            <!-- 开始匹配 -->
            <button id="match" onclick="findMatch()">开始匹配</button>
        </div>
    </div>
</body>
</html>

hall.css

css 复制代码
.container {
    height: calc(100% - 50px);
    display: flex;
    justify-content: center;
    align-items: center;
}

.container .dialog {
    height: 350px;
    width: 299px;
    background-color: white;
    border-radius: 20px;
    padding-top: 30px;
    display: flex;
    justify-content: center;
    /* align-items: center; */
    flex-wrap: wrap
}

.dialog *{
    display: flex;
    justify-content: center;
    align-items: center;
}

.dialog #screen {
    width: 250px;
    height: 150px;
    background-color: wheat;
    border-radius: 10px;
}

.dialog #match {
    width: 150px;
    height: 40px;
    background-color: rgb(255, 159, 33);
    border-radius: 10px;
}

.dialog #match:active {
    background-color: rgb(204, 128, 21);
}

2. 获取用户信息接口

当用户进入 游戏大厅时,就应该获取到登录用户的信息显示到页面上,我们使用js代码从访问后端接口获取信息:

html 复制代码
    <script src="js/jquery.min.js"></script>
    <script>
        $.ajax({
            type: 'post',
            url: '/user/getLoginUser',
            success: function(result) {
                if(result.username != null) {
                    let screen = document.querySelector("#screen");
                    screen.innerHTML = '当前玩家:' + result.username + '<br>天梯积分:' + 
                    result.score + '<br>比赛场次:' + result.totalCount + 
                    '<br>获胜场次:' + result.winCount;
                }else{
                    alert("获取用户信息失败,请重新登录");
                    location.href = "/login.html";
                }
            },
            error: function() {
                alert("获取用户信息失败");
            }
        });
    </script>

运行效果:

2. WebSocket前端代码

当用户点击匹配按钮时,需要告知服务器该用户要进行匹配,服务器如果接收到则立即回复表示正在匹配,当匹配成功服务器则又需要发送匹配信息给客户端。这里涉及到服务器主动给客户端发送消息的场景,所以我们使用websocket实现

2.1 初始化websocket

javascript 复制代码
let webSocket = new WebSocket('ws://127.0.0.1:8080/findMatch');
        webSocket.onopen = function() {
            console.log("连接成功");
        }
        webSocket.onclose = function() {
            console.log("连接关闭");
        }
        webSocket.onerror = function() {
            console.log("error");
        }

        //页面关闭时释放webSocket
        window.onbeforeunload = function() {
            webSocket.close();
        }

        //处理服务器发送的消息
        webSocket.onmessage = function(e) {

        }

        function findMatch() {
            //检查websocket连接
            if(webSocket.readyState == webSocket.OPEN) {

            }else{
                alert("连接断开,请重新登录");
                location.href = "/login.html";
            }
        }

2.2 实现findMatch()方法

点击开始匹配按钮后就会执行findMatch方法,进入匹配状态,此时我们可以把开始匹配按钮替换成取消匹配按钮,再次点击则会向服务器发送取消匹配请求。

javascript 复制代码
function findMatch() {
            //检查websocket连接
            if(webSocket.readyState == webSocket.OPEN) {
                if($("#match").text() == '开始匹配') {
                    console.log("开始匹配");
                    webSocket.send(JSON.stringify({
                        message: 'startMatch' //约定startMatch表示开始匹配
                    }));
                }else if($("#match").text() == '匹配中...') {
                    console.log("停止匹配");
                    webSocket.send(JSON.stringify({
                        message: 'stopMatch' //约定stopMatch表示停止匹配
                    }));
                }
            }else{
                alert("连接断开,请重新登录");
                location.href = "/login.html";
            }
        }

2.3 实现onmessage

我们约定服务器返回的响应为包含以下三个字段的json:

  • ok: true/false, //表示请求成功还是失败
  • errMsg:"错误信息", //请求失败返回错误信息
  • message: 'startMatch' / 'stopMatch' / 'success' //success表示请求成功
javascript 复制代码
//处理服务器发送的消息
        webSocket.onmessage = function(e) {
            //解析json字符串为js对象
            let resp = JSON.parse(e.data);
            if(!resp.ok) {
                console.log(resp.errMsg);
                return;
            }
            if(resp.message == 'startMatch') {
                //开始匹配请求发送成功正在匹配
                //替换按钮描述
                $("#match").text("匹配中...");
            }else if(resp.message == 'stopMatch') {
                //取消匹配请求发送成功已取消匹配
                //替换按钮描述
                $("#match").text("开始匹配");
            }else if(resp.message == 'success'){
                //匹配成功
                console.log("匹配成功! 进入游戏房间");
                locating.href = "/game.html";
            }else{
                console.log("非法响应 errMsg:" + resp.errMsg);
                
            }

        }

3. WebSocket后端代码

3.1 注册websocket

创建TextWebSocketHandler子类,重写如下方法:

javascript 复制代码
package org.ting.j20250110_gobang.websocket;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

@Component
public class MatchWebSocket extends TextWebSocketHandler {
    //连接成功后执行
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
    }
    //接收到请求后执行
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
    }
    //连接异常时执行
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
    }
    //连接正常断开后执行
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
    }
}

注册socket:

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import org.ting.j20250110_gobang.websocket.MatchWebSocket;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Autowired
    MatchWebSocket matchWebSocket;
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(matchWebSocket, "/findMatch") //注意路径和前端对应
                //添加拦截器获取到session,方便获取session中的用户信息
                .addInterceptors(new HttpSessionHandshakeInterceptor());
    }
}
相关推荐
会编程的吕洞宾13 分钟前
Spring Boot多环境配置实战 配置文件加载顺序与切换不再翻车
java·后端
额鹅恶饿呃15 分钟前
随着CentOS官方停服的时间越来越久,大量仍在使用CentOS7的企业和运维从业者
java·python·算法·c#·ruby
秋名RG20 分钟前
Java 异常处理全攻略:从入门到实战(JDK 21 版)
java·开发语言
SQL-First布道者29 分钟前
我为什么把 MyBatis 从项目中删了?
java·spring·tomcat·mybatis·mybatis plus·spring jdbc
公爵爱学习33 分钟前
无人机多点导航笔记
java·前端·笔记
萧瑟余晖1 小时前
Java深入解析篇五十五之Unsafe 机制详解
java
kakawzw1 小时前
mybatis源码笔记1——JDBC和整体架构
java·mybatis
sunshine22 girl1 小时前
Java学习一 环境配置1 安装JDK,配置环境变量
java·开发语言·学习
秋饼1 小时前
Spring AI Session API 深度实战:从 ChatMemory 平滑迁移到事件溯源的企业级短期记忆
java·ai·技术分享·后端开发
QCodingDev1 小时前
Spring AI 2.0企业级RAG实战:引用校验、无依据拒答与知识治理怎么做?
java·人工智能·spring·ai