[網頁五子棋][匹配模塊]服務器開發、用戶管理器(創建匹配請求/響應對象、處理連接成功、處理下線)

文章目錄

    • MatchAPI 類
    • 用戶管理器
      • 創建匹配請求/響應對象
      • 處理連接成功—afterConnectionEstablished
      • 處理下線——handleTransportError/afterConnectionClosed

MatchAPI 類

創建 api.MatchAPI,繼承自 TextWebSocketHandler 作為處理 WebSocket 請求的入口類

  • 準備好一個 ObjectMapper,后續用來處理 JSON 數據
package org.example.java_gobang.api;  import com.fasterxml.jackson.databind.ObjectMapper;  
import org.springframework.stereotype.Component;  
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;  //通過這個類,來處理匹配功能中的 websocket 請求  
@Component  
public class MatchAPI extends TextWebSocketHandler {  // 稍后處理 JSON 會用到的對象  private ObjectMapper objectMapper = new ObjectMapper();  @Override  public void afterConnectionEstablished(WebSocketSession session) throws Exception {  }  @Override  protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {  }  @Override  public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {  }  @Override  public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {  }  
}

修改 config.WebSocketConfig,把 MatchAPI 加進去

  • addHandler 之后,再加上一個 .addInterceptors(new HttpSessionHandshakeInterceptor()) 代碼
  • 這樣可以把之前登錄過程往 HttpSession 中存放的數據(主要是 User 對象),放到 WebSocketSession 中,方便后續獲取到當前用戶的信息

在注冊 websocket API 的時候,就需要把前面準備好的 HttpSession 給搞過來(搞到 WebSocketSession 中)

  • 用戶登錄就會給 HttpSession 中保存用戶的信息
  • 你點了一下匹配按鈕,就需要告訴服務器當前是誰在點按鈕
package org.example.java_gobang.config;  import org.example.java_gobang.api.MatchAPI;  
import org.example.java_gobang.api.TestAPI;  
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;  /**  * 這個類是用來注冊 WebSocketHandler 的配置類  * 這個類是來告訴 Spring(websocket),哪一個類是和哪一個路徑相匹配的  */  
@Configuration  
@EnableWebSocket // 讓 Spring 框架知道這個類是用來配置 websocket 的  
public class WebSocketConfig implements WebSocketConfigurer {  @Autowired  private TestAPI testAPI;  @Autowired  private MatchAPI matchAPI;  @Override  public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {  // 當我們的客戶端連接到 /test 路徑的時候,就會觸發到當前的 TestAPI,然后調用執行里面的方法  webSocketHandlerRegistry.addHandler(testAPI, "/test");  webSocketHandlerRegistry.addHandler(matchAPI,"/findMatch")  .addInterceptors(new HttpSessionHandshakeInterceptor());  }  
}
  • 通過 .addInterceptors(new HttpSessionHandshakeInterceptor() 這個操作來把 HttpSession ?的屬性放到 WebSocketsession
  • 然后就可以在 WebSocket 代碼中 WebSocketSession ?拿到 HttpSession 中的attribute

用戶管理器

此處我們需要能夠保存和表示用戶的上線狀態

之所以要維護用戶的在線狀態,目的是為了能夠在代碼中比較方便的獲取到某個用戶當前的 websocket 會話

  • 從而可以通過這個會話來給客戶端發送信息
  • 同時也可以感知到他們的在線/離線狀態

可以使用一個哈希表來保存當前用戶的在線狀態

  • key 就是用戶 id
  • value 就是用戶當前使用的 websocket 會話

創建 game.OnlineUserManager 類,借助這個類, ???可以判定??是否是在線, 同時也可以進??便的獲取到 Session 從?給客?端回話

  • 當玩家建立好 websocket 連接,則將鍵值對加入 OnlineUserManager
  • 當玩家斷開 websocket 連接,則將鍵值對從 OnlineUserManager 中刪除
  • 在玩家連接好的過程中,隨時可以通過 userId 來查詢對應的會話,以便向客戶端返回數據
package org.example.java_gobang.game;  import org.springframework.stereotype.Component;  
import org.springframework.web.socket.WebSocketSession;  import java.util.HashMap;  @Component  
public class OnlineUserManager {  // 這個哈希表就用來表示當前用戶在游戲大廳的在線狀態  private HashMap<Integer, WebSocketSession> gameHall = new HashMap<>();  public void enterGameHall(int userId, WebSocketSession webSocketSession) {  gameHall.put(userId, webSocketSession);  }  public void exitGameHall(int userId) {  gameHall.remove(userId);  }  public WebSocketSession getFromGameHall(int userId) {  return gameHall.get(userId);  }  
}

創建匹配請求/響應對象

創建 game.MatchRequest

package org.example.java_gobang.game;  // 這是表示一個 websocket 的匹配請求  
public class MatchRequest {  private String message = "";  public String getMessage() {  return message;  }  public void setMessage(String message) {  this.message = message;  }  
}

創建 game.MatchResponse

package org.example.java_gobang.game;  // 這是表示一個 websocket 的匹配響應  
public class MatchResponse {  private boolean ok;  private String reason;  private String message;  public boolean isOk() {  return ok;  }  public void setOk(boolean ok) {  this.ok = ok;  }  public String getReason() {  return reason;  }  public void setReason(String reason) {  this.reason = reason;  }  public String getMessage() {  return message;  }  public void setMessage(String message) {  this.message = message;  }  
}

處理連接成功—afterConnectionEstablished

實現 afterConnectionEstablished ?法

  • 通過參數中的 session 對象,拿到之前登錄時設置的 User 信息
  • 使用 onlineUserManager 來管理用戶的在線狀態
  • 先判定用戶是否是已經在線,如果在線則直接返回出錯(禁止一個賬號多開)
  • 設置玩家的上線狀態
@Override  
public void afterConnectionEstablished(WebSocketSession session) throws Exception {  // 玩家上線,加入到 OnlineUserManager 中  // 1. 獲取到當前用戶的身份信息(誰在游戲大廳中建立的連接)  //    此處的代碼,之所以能夠 getAttributes,全靠了在注冊 WebSocket 的時候,  //    加上的 .addInterceptors(new HttpSessionHandshakeInterceptor());    //    這個邏輯就把 HttpSession 中的 Attributes 都給拿到 WebSocketSession 中了  //    在 Http 登錄邏輯中,往 HttpSession 中存了 User 數據: (UserAPI)httpSession.setAttribute("user", user);  //    此時就可以在 WebSocketSession 中把之前 HttpSession 里存的 User 給拿到了  //    此處我們拿到的 user,是有可能為空的!  //    如果之前用戶壓根就沒有通過 HTTP 來進行登錄,直接就通過 /game_hall.html 這個 URL 來訪問游戲大廳頁面  //    此時就會出現 user 為空的情況(繞開登錄界面就會為空)  try {  User user = (User) session.getAttributes().get("user");  // 2. 拿到了身份信息之后,就可以把玩家設成在線狀態  onlineUserManager.enterGameHall(user.getUserId(), session);  System.out.println("玩家 " + user.getUsername() + "進入游戲大廳");  }catch (NullPointerException e) {  // 出現空指針異常,說明當前用戶的身份是空的,用戶未登錄  // 把當前用戶尚未登錄這個信息給返回回去  MatchResponse response = new MatchResponse();  response.setOk(false);  response.setReason("您未登錄! 不能進行后續匹配!");  session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));  }
  • session.sendMessage
    • 先通過 ObjectMapperMatchResponse 對象轉成 JSON 字符串
    • 然后再包裝上一層 TextMessage,再進行傳輸
    • TestMessage 就表示一個文本格式的 websocket 數據包

處理下線——handleTransportError/afterConnectionClosed

@Override  
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {  try {  // 玩家下線,從 OnlineUserManager 中刪除  User user = (User) session.getAttributes().get("user");  onlineUserManager.exitGameHall(user.getUserId());  } catch (NullPointerException e) {  e.printStackTrace();  MatchResponse response = new MatchResponse();  response.setOk(false);  response.setReason("您未登錄! 不能進行后續匹配!");  session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));  }  
}  @Override  
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {  try {  // 玩家下線,從 OnlineUserManager 中刪除  User user = (User) session.getAttributes().get("user");  onlineUserManager.exitGameHall(user.getUserId());  } catch (NullPointerException e) {  e.printStackTrace();  MatchResponse response = new MatchResponse();  response.setOk(false);  response.setReason("您未登錄! 不能進行后續匹配!");  session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));  }  
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907301.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907301.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907301.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

軟件測試的潛力與挑戰:從“質量守門員”到“工程效能催化劑”的進化

1. 潛力&#xff1a;為什么軟件測試的未來比想象中更廣闊&#xff1f; ? 行業趨勢驅動需求爆發 DevOps/持續交付&#xff1a;測試成為流水線的核心環節&#xff0c;自動化能力直接影響發布頻率&#xff08;案例&#xff1a;某頭部互聯網企業日均發布100次&#xff0c;依賴自動…

indel_snp_ssr_primer

好的&#xff0c;我們可以逐步分析這個 Perl 腳本的每個部分。腳本的主要功能是基于給定的 VCF 文件和參考基因組文件&#xff0c;設計引物并進行電子 PCR&#xff08;e-PCR&#xff09;分析。我們將從腳本的頭部和初始化部分開始講解。 第一部分&#xff1a;腳本頭部和初始化…

2.4GHz 射頻前端芯片AT2401C

射頻前端芯片作為無線通信系統的核心組件&#xff0c;涵蓋功率放大器&#xff08;PA&#xff09;、濾波器、開關、低噪聲放大器&#xff08;LNA&#xff09;等關鍵器件&#xff0c;其性能直接影響通信質量、功耗及信號穩定性。 AT2401C是一款面向 Zigbee&#xff0c;無線傳感網…

Batch Normalization[[

error surface如果很崎嶇,那么就代表比較難train,我們有沒有辦法去改變這個landscape呢 可以用batch normalization. 如果 ( x_1 ) 的取值范圍很小&#xff08;如 1, 2&#xff09;&#xff0c;而 ( x_2 ) 的取值范圍很大&#xff08;如 100, 200&#xff09;&#xff0c;那么…

c++結構化綁定

author: hjjdebug date: 2025年 05月 28日 星期三 15:57:58 CST descrip: c結構化綁定: 結構化綁定: 名稱辨析: 名稱叫綁定好還是叫解綁好&#xff1f; 解綁意思是原來是一個整體,現在被分成了若干個部分,所以叫解. 綁定強調的意思是. 被分解的某個變量,綁定到了整體的某個變量…

大數據治理:理論、實踐與未來展望(一)

文章目錄 一、大數據治理的定義與重要性&#xff08;一&#xff09;定義&#xff08;二&#xff09;重要性 二、大數據治理的應用場景&#xff08;一&#xff09;金融行業&#xff08;二&#xff09;醫療行業&#xff08;三&#xff09;制造業&#xff08;四&#xff09;零售行…

AI系統化學習月計劃6月計劃

以下是為技術總監設計的 AI系統化學習月計劃&#xff08;每天投入2小時&#xff0c;共30天&#xff09;&#xff0c;結合戰略思維、技術基礎、實戰應用和行業趨勢&#xff0c;幫助您快速掌握AI的核心知識&#xff0c;并轉化為業務決策能力。 第一周&#xff1a;AI基礎與戰略思維…

詳解MySQL調優

目錄 1. SQL 語句優 1.1 避免低效查詢 1.2 索引優化 1.3 分析執行計劃 2. 數據庫配置優化 2.1 核心參數調整 2.2 表結構與存儲引擎 2.3 存儲引擎選擇 3. 事務與鎖優化 3.1 事務控制 3.2 鎖機制優化 3.3 批量操作優化 4. 其他優化手段 4.1 監控與分析工具 4.2 讀寫…

VScode單雙引號、分號格式

1、settings.json中添加&#xff1a; 1 2 3 "prettier.semi": false, // 取消自動加分號 "prettier.singleQuote": true, // 保持單引號&#xff0c;不自動變雙引號 "prettier.trailingComma": "none" // 去掉結尾的逗號 2、如上一步…

自動駕駛規劃控制教程——不確定環境下的決策規劃

引言:駕馭未知——不確定性下的自動駕駛決策挑戰 自動駕駛汽車 (Autonomous Vehicles, AVs) 的愿景是徹底改變交通運輸的面貌,提高道路安全、提升交通效率、改善駕乘體驗。然而,要將這一愿景安全可靠地付諸實踐,自動駕駛系統必須能夠在復雜、動態且充滿不確定性的真實世界…

電纜中性點概念

電纜中性點概念 電纜中性點(也稱“中性點”或“中性線”)是電力系統和電氣設備中一個非常重要的概念,尤其在三相電系統中。下面是對中性點概念的系統性解釋。 1. 基本定義 中性點:三相電纜(A/B/C相)的電壓矢量交匯點,理想情況下三相平衡時該點電壓為零。對于星形(Y形…

MyBatis 動態 SQL 詳解:靈活構建強大查詢

MyBatis 的動態 SQL 功能是其最強大的特性之一&#xff0c;它允許開發者根據不同條件動態生成 SQL 語句&#xff0c;極大地提高了 SQL 的靈活性和復用性。本文將深入探討 MyBatis 的動態 SQL 功能&#xff0c;包括 OGNL 表達式的使用以及各種動態 SQL 元素&#xff08;如 if、c…

嵌入式自學第三十天(5.28)

&#xff08;1&#xff09;多線程資源競爭問題&#xff1a; 互斥&#xff1a;在多線程中對臨界資源的排他性訪問。 解決方案&#xff1a;互斥鎖 mutex互斥鎖在進程pcb塊&#xff0c;ret 為0說明別人在用&#xff0c;1說明空閑。 阻塞鎖 man pthread_mutex_init man pthread_…

【HW系列】—web常規漏洞(SQL注入與XSS)

SQL注入與XSS攻防解析&#xff08;安全防御指南&#xff09; 一、SQL注入基礎&#xff08;防御視角&#xff09; ??1. 簡介?? SQL注入是一種通過構造非預期SQL語句操縱數據庫的攻擊技術。作為開發者&#xff0c;需重點關注輸入驗證與查詢安全&#xff0c;建立全流量監測…

Accelerate 2025北亞巡展正式啟航!AI智御全球·引領安全新時代

近日&#xff0c;網絡安全行業年度盛會Accelerate 2025北亞巡展正式在深圳啟航&#xff01;智庫專家、產業領袖及Fortinet高管、產品技術團隊和300余位行業客戶齊聚一堂&#xff0c;圍繞“AI智御全球引領安全新時代”主題&#xff0c;共同探討AI時代網絡安全新范式。大會聚焦三…

RAG系統構建之嵌入模型性能優化完整指南

導讀&#xff1a;在企業級RAG系統的實際部署中&#xff0c;您是否遇到過這樣的困擾&#xff1a;嵌入計算成本不斷攀升&#xff0c;API調用頻繁觸及限制&#xff0c;而系統響應速度卻始終達不到用戶期望&#xff1f;這些看似分散的問題&#xff0c;實際上都指向同一個技術核心&a…

python 自動生成不同行高的word

python 自動生成不同行高的word # -*- coding: utf-8 -*- from docx import Document from docx.shared import Cm, Pt, Inches from docx.oxml import OxmlElement from docx.oxml.ns import qn from docx.enum.text import WD_ALIGN_PARAGRAPHclass DynamicTableGenerator:d…

如何訓練意志力

設定清晰的目標 目標需要是具體的&#xff0c;可實現的&#xff0c;有時間限制的。比如不要說“我要鍛煉”&#xff0c;而是改成“每周跑步3次&#xff0c;每次30分鐘”。 從小事開始 起步通常都是困難的&#xff0c;一開始定一個很大很復雜的任務也超出了自己的能力&#x…

FastAPI 依賴注入

依賴注入常用于以下場景&#xff1a; 共享業務邏輯&#xff08;復用相同的代碼邏輯&#xff09; 共享數據庫連接 實現安全、驗證、角色權限 等…… 上述場景均可以使用依賴注入&#xff0c;將代碼重復最小化。 創建依賴項 依賴項就是一個函數&#xff0c;且可以使用與路…

接口冪等性原理與方案總結

文章目錄 接口冪等概念典型場景核心解決方案一鎖二判三更新 方案選型對比 接口冪等概念 定義&#xff1a;無論調用接口多少次&#xff0c;對系統的影響與單次調用一樣 范疇&#xff1a;在后端開發中&#xff0c;通常更關注寫接口的冪等&#xff0c;因為寫接口才會對系統數據造…