25.【.NET8 實戰--孢子記賬--從單體到微服務--轉向微服務】--單體轉微服務--用戶服務接口

用戶管理是任何系統的基礎功能之一,本篇介紹了如何實現一個完整的用戶管理模塊,包括用戶信息的增刪改查、用戶狀態管理、分頁查詢、數據驗證和權限控制。核心代碼實現部分涵蓋了控制器(UserController)、服務接口(IUserService)、請求/響應模型以及服務實現(UserServiceImpl),并詳細說明了各接口的功能,如獲取用戶信息、分頁獲取用戶列表、刪除用戶、禁用/啟用用戶和更新用戶信息。最佳實踐建議包括數據驗證、性能優化、安全性和代碼組織等方面,強調了使用數據注解、異步方法、依賴注入、權限控制和統一響應格式等措施。使用示例展示了如何通過HTTP請求獲取用戶列表、更新用戶信息和禁用用戶。注意事項提醒用戶刪除操作建議采用軟刪除、敏感操作需記錄日志、用戶狀態變更應通知相關系統、響應中不返回敏感信息以及并發操作的處理。該用戶管理模塊為基本的CRUD操作提供了實現基礎,并可根據實際需求擴展更多功能,如增加查詢條件、導入導出、操作日志等。

Tip:由于大部分內容跟單體應用中的知識點一樣,因此我們只講解核心設計要點和高級特性實現。

一、核心設計要點

1.1 用戶狀態管理
/// <summary>
/// 禁用/啟用用戶
/// </summary>
/// <param name="id"></param>
/// <param name="isDisabled"></param>
/// <returns></returns>
public async Task DisableUser(long id, bool isDisabled)
{var user = await _userManager.FindByIdAsync(id.ToString());if (user == null){throw new NotFoundException($"用戶不存在");}if (isDisabled){user.LockoutEnd = DateTimeOffset.UtcNow.AddYears(100); // 設置一個很遠的未來時間}else{user.LockoutEnd = null; // 解除鎖定}user.LockoutEnabled = isDisabled;var result = await _userManager.UpdateAsync(user);if (!result.Succeeded){throw new BadRequestException($"禁用/啟用用戶失敗");}
}

這段代碼是一個用于“禁用/啟用用戶”的服務方法,常見于基于ASP.NET Core Identity的用戶管理系統。下面我們詳細講解代碼和設計思路。

代碼接收接收用戶ID和一個布爾值,表示是否禁用用戶。如果禁用,則將用戶的鎖定時間設置為100年后;如果啟用,則將鎖定時間設置為null,表示解除鎖定。其中LockoutEnd屬性用于控制用戶鎖定時間,LockoutEnabled屬性用于啟用或禁用鎖定功能。代碼中使用了_userManager來管理用戶對象,FindByIdAsync方法用于查找用戶,UpdateAsync方法用于更新用戶信息。在查找用戶時,如果找不到用戶,則拋出“用戶不存在”異常;在更新用戶信息時,如果更新失敗,則拋出“禁用/啟用用戶失敗”異常。

代碼的設計思路很簡單,我們采用ASP.NET Core Identity的鎖定機制,通過設置LockoutEndLockoutEnabled屬性來控制用戶的登錄權限,而不是直接刪除或修改用戶的敏感信息,從而提升系統的安全性。其次,方法中通過拋出異常的方式處理各種錯誤情況,便于上層統一捕獲和處理,提高了代碼的可維護性。此外,該實現方式具有良好的擴展性,只需調整鎖定時間或相關條件,即可滿足臨時禁用、永久禁用等不同業務場景的需求。

在實際開發過程中,需要注意以下幾點。第一,只有當 LockoutEnabled 屬性設置為 true 時,LockoutEnd 的鎖定機制才會生效。其次,將鎖定時間設置為100年后雖然不能算作真正的“永久禁用”,但對于大多數業務場景來說已經足夠使用。此外,如果用戶已經處于禁用狀態,再次執行禁用操作不會引發錯誤,但建議在業務邏輯層面實現冪等性處理,以避免重復操作帶來的潛在問題。

Tip:通過Identity的鎖定機制實現了用戶的禁用和啟用,既安全又易于維護,是.NET項目中常見的用戶狀態管理方式。

1.2 分頁查詢優化
/// <summary>
/// 獲取用戶列表
/// </summary>
/// <param name="page"></param>
/// <returns></returns>
public async Task<PagedResponse<UserResponse>> GetUserList(UserPageRequest page)
{var query = _userManager.Users.AsQueryable();if (!string.IsNullOrEmpty(page.UserName)){query = query.Where(x => x.UserName.Contains(page.UserName));}if (!string.IsNullOrEmpty(page.Email)){query = query.Where(x => x.Email.Contains(page.Email));}// 使用單次查詢獲取總數和分頁數據var totalQuery = query;var pagedQuery = query.OrderByDescending(o => o.Id).Skip((page.Page - 1) * page.PageSize).Take(page.PageSize);// 并行執行兩個查詢var countTask = totalQuery.CountAsync();var usersTask = pagedQuery.ToListAsync();await Task.WhenAll(countTask, usersTask);int total = countTask.Result;List<SpUser> users = usersTask.Result;var result = new PagedResponse<UserResponse>{TotalRow = total,TotalPage = (int)Math.Ceiling((double)total / page.PageSize),Data = users.Select(x => new UserResponse{Id = x.Id,UserName = x.UserName,Email = x.Email,IsLocked = x.LockoutEnabled}).ToList()};return result;
}

這段代碼是一個用于獲取用戶列表的異步方法,常見于.NET后端服務中,主要實現了分頁、條件篩選和高效查詢。GetUserList方法是一個異步操作,返回類型為 Task<PagedResponse<UserResponse>>,用于獲取分頁后的用戶列表。參數 UserPageRequest page 封裝了分頁信息和篩選條件(如用戶名、郵箱等),便于靈活查詢用戶數據。這段代碼的設計思路是通過使用IQueryable接口來構建動態查詢,結合分頁和異步操作來提高性能和用戶體驗。其中_userManager.Users 獲取了所有用戶的可查詢對象,AsQueryable() 方法使得可以對用戶數據進行動態查詢。并且我們使用了LINQ的 Where 方法來根據用戶名和郵箱進行條件篩選,OrderByDescending 方法按用戶ID倒序排列,SkipTake 方法實現了分頁功能。這里要重點關注并行查詢總數和數據的實現,使用 Task.WhenAll 方法可以同時執行兩個異步查詢任務,分別獲取總記錄數和當前頁的用戶列表,從而提高查詢效率。

Tip:Task.WhenAll能提升性能,但要確保兩個查詢不會互相影響。

1.3 用戶信息更新
/// <summary>
/// 更新用戶信息
/// </summary>
/// <param name="id"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task UpdateUser(long id, UserUpdateRequest user)
{var spUser = await _userManager.FindByIdAsync(id.ToString());if (spUser == null){throw new NotFoundException($"用戶不存在");}spUser.UserName = user.UserName;spUser.Email = user.Email;var result = await _userManager.UpdateAsync(spUser);if (!result.Succeeded){throw new BadRequestException($"更新用戶失敗");}
}

這段代碼是一個用于更新用戶信息的服務方法,常見于基于ASP.NET Core Identity的用戶管理系統。代碼接收用戶ID和一個包含更新信息的請求對象 UserUpdateRequest。首先通過 _userManager.FindByIdAsync 方法查找用戶,如果找不到用戶,則拋出“用戶不存在”異常。接著,將請求中的新信息賦值給用戶對象的相應屬性,如用戶名、郵箱和手機號。最后,使用 _userManager.UpdateAsync 方法更新用戶信息,如果更新失敗,則拋出“更新用戶信息失敗”異常,并將錯誤信息拼接成字符串返回。

代碼的設計思路很簡單,我們采用ASP.NET Core Identity的用戶管理功能,通過 _userManager 來操作用戶對象。首先通過ID查找用戶,確保用戶存在;然后更新用戶信息,確保數據的完整性和一致性。最后通過拋出異常的方式處理各種錯誤情況,便于上層統一捕獲和處理,提高了代碼的可維護性。此外,該實現方式具有良好的擴展性,只需調整請求對象中的屬性,即可滿足不同業務場景下的用戶信息更新需求。

二、高級特性實現

2.1 用戶角色關聯
/// <summary>
/// 獲取用戶信息
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<UserResponse?> GetUserInfo(long id)
{// 嘗試從緩存獲取string cacheKey = $"user:{id}";var cachedUser = await _redis.GetStringAsync(cacheKey);if (!string.IsNullOrEmpty(cachedUser)){return JsonSerializer.Deserialize<UserResponse>(cachedUser);}// 緩存未命中,從數據庫查詢var user = await _userManager.FindByIdAsync(id.ToString());if (user == null){throw new NotFoundException($"用戶不存在");}var response = new UserResponse{Id = user.Id,UserName = user.UserName,Email = user.Email,IsLocked = user.LockoutEnabled};// 緩存結果,設置適當的過期時間await _redis.SetStringAsync(cacheKey, JsonSerializer.Serialize(response), 60 * 10);return response;
}

這段代碼是一個用于獲取用戶信息的服務方法。代碼首先嘗試從Redis緩存中獲取用戶信息,如果緩存命中,則直接返回緩存中的數據;如果緩存未命中,則從數據庫中查詢用戶信息,并將查詢結果存入緩存中,以便下次快速訪問。代碼使用了 _userManager.FindByIdAsync 方法來查找用戶,如果找不到用戶,則拋出“用戶不存在”異常。查詢到的用戶信息被封裝成 UserResponse 對象,并存入Redis緩存中,設置了10分鐘的過期時間。

代碼的設計思路是通過使用Redis緩存來提高用戶信息查詢的性能,減少數據庫訪問次數。首先嘗試從緩存中獲取數據,如果緩存命中,則直接返回;如果緩存未命中,則從數據庫查詢并更新緩存。這樣可以顯著提高查詢速度,尤其是在高并發場景下。此外,使用Redis作為緩存存儲,可以有效降低數據庫負載,提高系統的整體性能。

Tip:使用Redis緩存用戶信息可以顯著提高查詢性能,尤其是在高并發場景下。

三、總結

用戶管理模塊是任何系統的基礎功能之一,本篇介紹了如何實現一個完整的用戶管理模塊,包括用戶信息的增刪改查、用戶狀態管理、分頁查詢、數據驗證和權限控制。核心代碼實現部分涵蓋了控制器(UserController)、服務接口(IUserService)、請求/響應模型以及服務實現(UserServiceImpl),并詳細說明了各接口的功能,如獲取用戶信息、分頁獲取用戶列表、刪除用戶、禁用/啟用用戶和更新用戶信息。

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

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

相關文章

基于深度學習的無人機軌跡預測

完整代碼見文末 隨著無人機技術的不斷發展,無人機在農業、物流、監控等領域的應用日益廣泛。精準的軌跡預測不僅能夠提高無人機飛行的效率和安全性,還能在應對復雜環境下的突發狀況時做出迅速反應。因此,基于深度學習的無人機軌跡預測已成為當前研究和應用的熱門方向。 無…

AUTOSAR實戰教程--DoIP_02_診斷鏈路建立流程

第一步&#xff1a;DoIP實體車輛聲明/診斷儀車輛識別請求 打開激活線以后&#xff0c;DoIP實體發的三幀車輛聲明報文。其中包含了DoIP實體的診斷邏輯地址&#xff08;可以類比DoCAN的物理請求/響應地址&#xff09;&#xff0c;對應車輛的VIN碼&#xff08;若已配置&#xff0…

跟我學c++中級篇——多線程中的文件處理

一、文件處理 作為IO處理的一種重要場景&#xff0c;文件處理是幾乎所有編程都無法繞過的一個情況。稍微復雜的一些的程序都可能需要文件處理&#xff0c;不管這種文件處理對開發者來說是顯式的還是隱式的。相對于其它語言&#xff0c;C并未提供多么好的文件處理API接口&#…

Flutter知識點匯總

Flutter架構解析 1. Flutter 是什么?它與其他移動開發框架有什么不同? Flutter 是 Google 開發的開源移動應用開發框架,可用于快速構建高性能、高保真的移動應用(iOS 和 Android),也支持 Web、桌面和嵌入式設備。。它與其他移動開發框架(如 React Native、Xamarin、原…

【會員專享數據】1980—2022年中國逐日月年潛在蒸散發柵格數據

氣象數據是我們在各項研究中都經常使用的數據&#xff0c;尤其是高精度的氣象數據應用價值非常高。 之前我們分享過研究者張凌, 胡英屹等發布在國家冰川凍土沙漠科學數據中心平臺上的nc格式的1980—2022年中國高分辨率逐日、逐月、逐年氣象數據&#xff01;很多小伙伴拿到數據…

前端打包工具簡單介紹

前端打包工具簡單介紹 一、Webpack 架構與插件機制 1. Webpack 架構核心組成 Entry&#xff08;入口&#xff09; 指定應用的起點文件&#xff0c;比如 src/index.js。 Module&#xff08;模塊&#xff09; Webpack 把項目當作模塊圖&#xff0c;模塊可以是 JS、CSS、圖片等…

工業控制核心引擎高性能MCU——MM32F5370

RAMSUN提供的MM32F5370搭載180MHz Arm China Star-MC1處理器&#xff0c;集成DSP、FPU與三角函數加速單元&#xff08;CORDIC&#xff09;&#xff0c;輕松應對復雜算法需求。其技術亮點包括&#xff1a; 超高精度PWM&#xff1a;8通道208ps級高精度PWM輸出&#xff0c;滿足儲能…

AI架構師修煉之道

1 AI時代的架構革命 與傳統軟件開發和軟件架構師相比&#xff0c;AI架構師面臨著三重范式轉換&#xff1a; 1.1 技術維度&#xff0c;需處理異構算力調度與模型生命周期管理的復雜性&#xff1b; 1.2 系統維度&#xff0c;需平衡實時性與資源約束的矛盾&#xff1b; 1.3 價…

數學建模期末速成 主成分分析的基本步驟

設有 n n n個研究對象&#xff0c; m m m個指標變量 x 1 , x 2 , ? , x m x_1,x_2,\cdots,x_m x1?,x2?,?,xm?&#xff0c;第 i i i個對象關于第 j j j個指標取值為 a i j a_{ij} aij?,構造數據矩陣 A ( a i j ) n m A\left(\begin{array}{c}a_{ij}\end{array}\right)_{…

博圖 SCL 編程技巧:靈活實現上升沿與下降沿檢測案例分享(上)

博圖 SCL 編程技巧&#xff1a;靈活實現上升沿與下降沿檢測案例分享 在 PLC 編程中&#xff0c;檢測信號從 0 變為 1 (上升沿) 或從 1 變為 0 (下降沿) 是最基礎也是最關鍵的操作之一。它常用于啟動單次動作、計數、狀態切換等場景。在西門子 TIA Portal 環境中&#xff0c;雖…

深度學習入門Day3--魚書學習(2)

這倆天剛忙完答辯的事情&#xff0c;終于有時間學習了 一、3層神經網絡實現 1.本節中的符號使用說明。 w 12 ( 1 ) w_{12}^{(1)} w12(1)?表示前一層的第2個神經元 x 2 x_{2} x2?到后一層的第一個神經元 a 1 a_{1} a1?的權重。權重右下角按照“后一層的索引號、前一層的索引…

服務器 | Centos 9 系統中,如何部署SpringBoot后端項目?

系列文章目錄 虛擬機 | Ubuntu 安裝流程以及界面太小問題解決 虛擬機 | Ubuntu圖形化系統&#xff1a; open-vm-tools安裝失敗以及實現文件拖放 虛擬機 | Ubuntu操作系統&#xff1a;su和sudo理解及如何處理忘記root密碼 文章目錄 系列文章目錄前言一、環境介紹二、 使用syst…

CNN核心機制深度解析:卷積池化原理 PyTorch實現經典網絡

本文較長&#xff0c;建議點贊收藏&#xff0c;以免遺失。更多AI大模型應用開發學習視頻及資料&#xff0c;盡在聚客AI學院。 本文系統講解CNN核心原理、經典網絡架構和圖像分類實戰&#xff0c;涵蓋卷積層、池化層、LeNet/AlexNet/VGG/ResNet設計思想&#xff0c;并提供CIFAR-…

6個月Python學習計劃 Day 17 - 繼承、多態與魔術方法

第三周 Day 4 &#x1f3af; 今日目標 理解類的繼承和方法重寫掌握多態思想及其實際應用了解并使用常見的魔術方法&#xff08;如 str、len 等&#xff09; &#x1f9ec; 類的繼承&#xff08;Inheritance&#xff09; Python 支持單繼承與多繼承&#xff0c;常用語法如下&…

抖音怎么下載視頻

抖音作為一款短視頻社交平臺&#xff0c;憑借其獨特的短視頻形式和豐富的內容&#xff0c;吸引了大量用戶。有些用戶在欣賞完抖音視頻后&#xff0c;想要將其保存下來&#xff0c;以便日后觀看。如何在抖音下載視頻呢&#xff1f;本文將為您詳細介紹抖音視頻下載的技巧和方法。…

使用MinIO搭建自己的分布式文件存儲

目錄 引言&#xff1a; 一.什么是 MinIO &#xff1f; 二.MinIO 的安裝與部署&#xff1a; 三.Spring Cloud 集成 MinIO&#xff1a; 1.前提準備&#xff1a; &#xff08;1&#xff09;安裝依賴&#xff1a; &#xff08;2&#xff09;配置MinIO連接&#xff1a; &…

uni-app 如何實現選擇和上傳非圖像、視頻文件?

在 uni-app 中實現選擇和上傳非圖像、視頻文件&#xff0c;可根據不同端&#xff08;App、H5、小程序&#xff09;的特點&#xff0c;采用以下方法&#xff1a; 一、通用思路&#xff08;多端適配優先推薦&#xff09; 借助 uni.chooseFile 選擇文件&#xff0c;再用 uni.upl…

正點原子[第三期]Arm(iMX6U)Linux移植學習筆記-12.1 Linux內核啟動流程簡介

前言&#xff1a; 本文是根據嗶哩嗶哩網站上“Arm(iMX6U)Linux系統移植和根文件系統構鍵篇”視頻的學習筆記&#xff0c;在這里會記錄下正點原子 I.MX6ULL 開發板的配套視頻教程所作的實驗和學習筆記內容。本文大量引用了正點原子教學視頻和鏈接中的內容。 引用&#xff1a; …

UDP與TCP通信協議技術解析

文章目錄 協議基礎原理TCP&#xff1a;可靠的面向連接通信UDP&#xff1a;高效的無連接通信 性能特征分析TCP性能表現UDP性能表現 應用場景分析TCP適用場景UDP適用場景 技術實現考量錯誤處理策略網絡資源利用 選擇決策框架可靠性需求評估性能要求分析 混合方案設計協議組合策略…

mysql 頁的理解和實際分析

目錄 頁&#xff08;Page&#xff09;是 Innodb 存儲引擎用于管理數據的最小磁盤單位B樹的一般高度記錄在頁中的存儲 innodb ibd文件innodb 頁類型分析ibd文件查看數據表的行格式查看ibd文件 分析 ibd的第4個頁&#xff1a;B-tree Node類型先分析File Header(38字節-描述頁信息…