我們的游戲大廳界面主要需要包含兩個功能,一是顯示用戶信息,二是匹配游戲按鈕
1. 頁面實現
hall.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
.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代碼從訪問后端接口獲取信息:
<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
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");}//頁面關閉時釋放webSocketwindow.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方法,進入匹配狀態,此時我們可以把開始匹配按鈕替換成取消匹配按鈕,再次點擊則會向服務器發送取消匹配請求。
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表示請求成功
//處理服務器發送的消息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子類,重寫如下方法:?
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 {//連接成功后執行@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {super.afterConnectionEstablished(session);}//接收到請求后執行@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {super.handleTextMessage(session, message);}//連接異常時執行@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {super.handleTransportError(session, exception);}//連接正常斷開后執行@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {super.afterConnectionClosed(session, status);}
}
注冊socket:
?
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 {@AutowiredMatchWebSocket matchWebSocket;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(matchWebSocket, "/findMatch") //注意路徑和前端對應//添加攔截器獲取到session,方便獲取session中的用戶信息.addInterceptors(new HttpSessionHandshakeInterceptor());}
}