管理系統(tǒng)畢設(shè):從選課并發(fā)到權(quán)限設(shè)計全解析)
又到一年畢業(yè)設(shè)計季Java方向里“基于Spring Boot的教務(wù)管理系統(tǒng)”這類題目幾乎是每年都會出現(xiàn)的熱門選題。作為去年完整帶完一個類似課題的過來人我可以負(fù)責(zé)任地告訴你這題選得穩(wěn)但能不能順利答辯過關(guān)取決于你做系統(tǒng)時有沒有把權(quán)限、事務(wù)、并發(fā)這幾個關(guān)鍵問題想清楚。這篇文章不打算貼一整段代碼讓你抄那樣沒意義。我要拆的是這一類項目從0到1的完整思考鏈路為什么選這個課題、技術(shù)棧怎么定、數(shù)據(jù)庫怎么建模、核心業(yè)務(wù)邏輯怎么落、前后端聯(lián)調(diào)時踩過哪些坑。你照著這個思路自己重寫一遍不僅能應(yīng)付畢業(yè)設(shè)計還能在論文的“技術(shù)難點”章節(jié)寫出真正有深度的內(nèi)容而不是湊字?jǐn)?shù)的廢話。1. 課題定位與技術(shù)選型為什么教務(wù)管理系統(tǒng)是Java畢設(shè)的“安全牌”1.1 教務(wù)場景里到底藏著哪些真實痛點先說課題本身的業(yè)務(wù)價值。如果你去問任何一所高校的教務(wù)老師他們?nèi)粘9ぷ鞯恼鎸崰顟B(tài)一定包含這些場景課程安排靠Excel表格流轉(zhuǎn)學(xué)生選課在某個舊系統(tǒng)里卡到崩潰成績登記完了又因為格式不統(tǒng)一要反復(fù)返工。教務(wù)管理系統(tǒng)要解決的就是把這些分散的業(yè)務(wù)集中到一套可操作的Web系統(tǒng)里教務(wù)管理員維護(hù)課程數(shù)據(jù)、發(fā)布開課計劃學(xué)生在線選課退課教師錄入成績學(xué)生再查詢成績。這個業(yè)務(wù)模型太適合做成畢業(yè)設(shè)計了它不是一個“玩具項目”而是有真實業(yè)務(wù)約束的完整系統(tǒng)。你要處理的核心難點在選課和成績兩個環(huán)節(jié)選課要控制課程容量避免超選成績要對不同角色做權(quán)限隔離教師不能改別人的課程成績。這些約束天然地引導(dǎo)你去思考事務(wù)、并發(fā)、權(quán)限校驗而這些正是答辯時最容易問倒人的地方。1.2 技術(shù)棧怎么選才能既省事又不掉價Spring Boot作為主框架在Java畢業(yè)設(shè)計里是絕對的主流選擇原因很直白它把傳統(tǒng)SSHSpring MVC Spring Hibernate那一大堆XML配置全部簡化成了自動配置和注解你從零搭一個Web項目到跑起來可能只需要幾分鐘內(nèi)嵌的Tomcat也讓你不用額外去裝服務(wù)器環(huán)境。我比較推薦的技術(shù)棧組合是Spring Boot MyBatis Plus MySQL前端可以選Thymeleaf服務(wù)端渲染也可以做成前后端分離的Vue Element UI。這里有個權(quán)衡Thymeleaf適合想要快速跑通全流程、不想處理跨域和前端工程化的同學(xué)所有頁面由后端渲染部署時打成Jar包就行。Vue 前后端分離適合想在論文里多寫一章“前后端分離架構(gòu)設(shè)計”的同學(xué)但相應(yīng)地要處理跨域、Token鑒權(quán)、前端打包這些問題。數(shù)據(jù)庫用MySQL就夠了別為了顯得高級去碰PostgreSQL或MongoDB除非你的選題已經(jīng)明確要求。MyBatis Plus在日常CRUD上能省大量SQL編寫時間學(xué)習(xí)成本也低。1.3 功能范圍怎么定才能做到“麻雀雖小五臟俱全”我見過不少同學(xué)設(shè)計的教務(wù)管理系統(tǒng)功能表比企業(yè)ERP還復(fù)雜排課、調(diào)課、教室申請、畢業(yè)審核全塞進(jìn)去結(jié)果做了三個月連選課功能都還沒跑通。畢業(yè)設(shè)計不是商業(yè)軟件功能范圍必須收斂。合理的范圍建議聚焦三大角色、四條核心鏈路管理員用戶管理、課程管理、開課管理、選課截止時間設(shè)置教師查看授課列表、錄入成績、查看所授課程選課名單學(xué)生選課退課、查看已選課程、查詢成績、查看公告這四條鏈路是管理員維護(hù)課程并發(fā)布開課、學(xué)生選課退課、教師錄入成績、學(xué)生查詢成績。你看每條鏈路都完整覆蓋了一個業(yè)務(wù)閉環(huán)系統(tǒng)看起來不臃腫論文里能展示的截圖和用例又足夠多。2. 數(shù)據(jù)庫建模與權(quán)限設(shè)計項目上限由這一部分決定2.1 用戶角色表直接寫死字段還是引入RBAC用戶與角色的關(guān)系處理是教務(wù)管理系統(tǒng)里第一個暴露設(shè)計水平的地方。最基礎(chǔ)的做法是用戶表里加一個role字段值就是“admin”“teacher”“student”這種字符串用枚舉去判斷當(dāng)前用戶的角色權(quán)限。這個方案在功能實現(xiàn)上沒有任何問題代碼寫起來也快。但如果你想讓論文更有技術(shù)含量建議改成簡單的RBAC模型用戶表(user)、角色表(role)、用戶角色關(guān)聯(lián)表(user_role)。雖然管理員的角色基本固定但RBAC的好處在于以后擴(kuò)展班主任、輔導(dǎo)員、教務(wù)秘書這些角色時不需要改表結(jié)構(gòu)只需往角色表里加記錄。更重要的是這個設(shè)計能在論文的“系統(tǒng)設(shè)計”章節(jié)畫出三張標(biāo)準(zhǔn)的表結(jié)構(gòu)圖顯得你的系統(tǒng)有擴(kuò)展性而不是一錘子買賣。學(xué)生和教師的信息建議不要堆在用戶表里。用戶表只存用戶名、密碼、昵稱、角色這些登錄相關(guān)的字段教師信息表(teacher)和學(xué)籍信息表(student)通過user_id和用戶表關(guān)聯(lián)。這樣做的好處是表結(jié)構(gòu)語義清晰教師有職稱、所屬教研室學(xué)生有學(xué)號、入學(xué)年份、專業(yè)如果全塞進(jìn)用戶表后期查詢和維護(hù)都會很別扭。2.2 核心業(yè)務(wù)表結(jié)構(gòu)拆解與關(guān)聯(lián)關(guān)系教務(wù)系統(tǒng)的核心業(yè)務(wù)表我建議至少要設(shè)計出以下這五張第一張是課程表(course)字段包括課程編碼、課程名稱、學(xué)分、學(xué)時、課程簡介。課程是“基礎(chǔ)資料”類似于商品庫里的商品主數(shù)據(jù)。第二張是開課表(course_open)這是很容易被忽略但是最關(guān)鍵的一張表。它記錄的是“本學(xué)期某老師在某時間開設(shè)了某門課”字段包含開課學(xué)期、授課教師ID、上課時間地點、選課容量、已選人數(shù)、狀態(tài)。為什么需要一個開課表因為同一門課程在不同學(xué)期可能由不同老師開設(shè)、容量也不一樣如果把授課教師和上課時間直接放課程表就沒法表達(dá)這種動態(tài)關(guān)系。第三張是選課表(course_selection)字段包括選課ID、學(xué)生ID、開課ID、選課時間。我特別提醒這張表一定要加聯(lián)合唯一約束索引建立在(student_id, course_open_id)上否則并發(fā)環(huán)境下一定會出現(xiàn)重復(fù)選課的數(shù)據(jù)臟記錄。這是我在實際項目中踩過的坑后面單獨講。第四張是成績表(score)字段包括成績ID、學(xué)生ID、開課ID、成績值、錄入時間、備注。成績表跟選課表是什么關(guān)系一般建議成績表單獨存在而不是直接在選課表上加一個成績字段。雖然有些系統(tǒng)會直接復(fù)用選課記錄但獨立的成績表更利于教師錄入、學(xué)生查詢、管理員統(tǒng)計成績分布這些操作。第五張是公告表(notice)用于管理員發(fā)布通知。2.3 選課表聯(lián)合唯一約束一次并發(fā)問題的前車之鑒這里說一個真實項目里的教訓(xùn)。某同學(xué)做選課功能時選課表的定義只把主鍵ID設(shè)成自增沒有加任何唯一約束然后寫了一個“先判斷是否已選過再插入新記錄”的邏輯。單用戶測試完全正常一旦幾十個學(xué)生同時點擊選課數(shù)據(jù)庫中就會出現(xiàn)同一個人選了同一門課兩次的數(shù)據(jù)。原因并不復(fù)雜兩個請求同時通過了“是否已選過”的判斷然后都執(zhí)行了插入因為數(shù)據(jù)庫層面沒有任何約束阻止重復(fù)數(shù)據(jù)寫入。解決辦法分兩層表結(jié)構(gòu)層加上(student_id, course_open_id)的聯(lián)合唯一約束這是最后一道防線代碼邏輯層選課前再加一次查詢校驗兩道防線同時存在才能叫可靠。我們在做模擬項目X時把這個坑寫進(jìn)了缺陷報告后來每次設(shè)計涉及用戶與業(yè)務(wù)數(shù)據(jù)關(guān)聯(lián)的表我都會第一時間問自己這個關(guān)聯(lián)關(guān)系在數(shù)據(jù)庫層面用什么約束來保護(hù)3. 后端核心實現(xiàn)把關(guān)鍵業(yè)務(wù)邏輯寫扎實3.1 項目分層與代碼結(jié)構(gòu)Spring Boot項目的包結(jié)構(gòu)建議按照功能模塊而不是技術(shù)類型來劃分。很多教材喜歡用comon、mapper、service、controller這種方式按層分包功能簡單時沒問題但一旦功能多了代碼會堆得很亂。我習(xí)慣的方式是主包下面先按業(yè)務(wù)模塊分比如system模塊用戶、角色、course模塊課程、開課、selection模塊選課、score模塊成績每個模塊內(nèi)部再放controller、service、mapper、entity、dto這些子包。這樣的結(jié)構(gòu)在做演示或后期擴(kuò)展時能快速定位“選課相關(guān)的所有代碼都在selection包里”不用在幾十個controller文件里翻來翻去。還有一個在畢設(shè)論文里加分的小點寫一個統(tǒng)一的Result返回類和全局異常處理器。統(tǒng)一返回類保證后端返回結(jié)構(gòu)一致類似{ code: 200, message: 操作成功, data: ... }全局異常處理器用RestControllerAdvice加ExceptionHandler處理業(yè)務(wù)異常、參數(shù)校驗異常、運行時異常這樣業(yè)務(wù)代碼里只需要throw一個自定義的BusinessException不用到處try-catch。答辯時如果老師問“你的系統(tǒng)怎么處理異?!蹦憧梢灾苯诱f出這套機(jī)制的設(shè)計理由。3.2 登錄鑒權(quán)與權(quán)限控制登錄鑒權(quán)這個問題答辯老師幾乎必問。常用方案有兩種Session方案和JWT方案。如果前端是Thymeleaf用Session方案最省事登錄成功后把用戶信息放進(jìn)Session攔截器里判斷當(dāng)前請求路徑是否需要登錄、當(dāng)前用戶角色是否能訪問。這個方案不需要引入額外依賴?yán)斫獬杀镜瓦m合畢設(shè)。如果前端是Vue這類分離項目建議用JWT登錄成功后后端簽發(fā)一個Token前端存在瀏覽器本地存儲每次請求在Header里加上Token后端通過攔截器解析Token確定用戶身份。攔截器里需要處理的邏輯是放行策略。登錄接口、注冊接口、靜態(tài)資源要放行其他接口統(tǒng)一走鑒權(quán)攔截器。角色權(quán)限的判斷可以在攔截器里根據(jù)請求路徑前綴攔截比如/api/admin/**只有管理員角色能訪問。這個規(guī)則比較死板但足夠用。如果想要更好看的實現(xiàn)可以引入自定義注解加AOP做權(quán)限控制論文里寫出來是個亮點但實現(xiàn)前要考慮自己是否真的掌握AOP原理否則答辯被追問會露餡。3.3 選課接口事務(wù)與并發(fā)控制的必修課選課接口是整個教務(wù)管理系統(tǒng)里最值得花時間設(shè)計的業(yè)務(wù)邏輯。它的完整流程至少包含四步校驗學(xué)生身份確認(rèn)當(dāng)前處于選課時間范圍內(nèi)。查詢該開課記錄判斷當(dāng)前已選人數(shù)是否小于容量。檢查該學(xué)生是否已經(jīng)選過這門課避免重復(fù)選課。插入選課記錄并將開課表的已選人數(shù)加1。仔細(xì)想想這四個步驟每一步之間都存在并發(fā)隱患。最常見的場景是課程只剩最后一個名額兩個學(xué)生同時操作兩個請求都讀到“已選人數(shù)容量-1”都認(rèn)為還有名額于是都插入選課記錄最后實際選課人數(shù)超出容量非常典型的超賣問題。解決這種問題必須在數(shù)據(jù)庫層面加約束。我的做法是不用先查再更新而是直接執(zhí)行一條帶條件的更新語句UPDATE course_open SET selected_count selected_count 1 WHERE id #{openId} AND selected_count capacity執(zhí)行這條語句后通過受影響行數(shù)判斷是否還有剩余名額如果結(jié)果是0說明課程已經(jīng)滿了直接拋出“課程已選滿”的異常如果結(jié)果是1才繼續(xù)插入選課記錄。為什么這樣有效因為UPDATE語句在數(shù)據(jù)庫行上會加鎖兩個并發(fā)請求同時更新同一行時只可能有一個先獲得行鎖后一個請求看到的是更新后的數(shù)據(jù)從而重新判斷容量條件。這就是數(shù)據(jù)庫層面的樂觀鎖思想用條件更新代替“查詢再更新”。再配上事務(wù)整個選課過程要么全部提交要么全部回滾。在Service方法上加上Transactional注解注意這個注解不能自己類里調(diào)用自己類的方法否則事務(wù)不會生效這個問題后面在常見問題章節(jié)單獨展開。3.4 教師錄入成績與權(quán)限校驗細(xì)節(jié)成績錄入的實現(xiàn)相對簡單但權(quán)限校驗的細(xì)節(jié)很容易被忽略。錄入成績接口接收的參數(shù)一般有開課ID、學(xué)生ID、成績值。問題是接口的調(diào)用者是否真的是這門課的授課教師如果不做校驗任何登錄用戶只要猜到開課ID和學(xué)生ID就能往接口里傳參數(shù)改成績這是嚴(yán)重的安全漏洞。正確的做法是在Service層先根據(jù)當(dāng)前登錄用戶的教師ID查詢授課列表判斷目標(biāo)開課ID是否在列表里不在就直接拋出“無權(quán)操作該課程成績”的異常。這一點務(wù)必要寫進(jìn)論文的“系統(tǒng)安全設(shè)計”章節(jié)哪怕只是兩段話也比簡單說“系統(tǒng)采用Spring Boot框架開發(fā)”能撐內(nèi)容。還有成績的范圍校驗0到100之間的整數(shù)或一位小數(shù)用參數(shù)校驗注解或者手動判斷都行。這里我用一個從實際開發(fā)中總結(jié)的經(jīng)驗提醒你修改成績比錄入成績更需要謹(jǐn)慎一定要記錄操作日志。成績表里加上updated_time字段擴(kuò)展一個score_log表記錄修改前后的值、操作人、操作時間。雖然畢業(yè)設(shè)計不需要做得像真實系統(tǒng)那么重但有個操作日志功能演示時可以給答辯老師展示“系統(tǒng)具備數(shù)據(jù)可追溯性”加分效果明顯。4. 前端頁面與接口聯(lián)調(diào)從接口到可演示頁面的最后一公里4.1 頁面規(guī)劃教務(wù)系統(tǒng)要哪些頁面才夠用前端頁面規(guī)劃不需要花哨但至少要覆蓋核心業(yè)務(wù)鏈路。按照三個角色劃分管理員端需要登錄頁、工作臺首頁、用戶管理頁增刪改查、課程管理頁、開課管理頁、公告發(fā)布頁。教師端需要授課列表頁、選課學(xué)生名單頁、成績錄入頁按學(xué)生批量錄入或逐條錄入。學(xué)生端需要待選課程列表頁、我的課表/已選課程頁、成績查詢頁、公告頁。頁面交互以表格和表單為主這是后臺管理系統(tǒng)的典型形態(tài)UI不用追求炫酷干凈整齊即可。如果是前后端分離項目用Element UI的表格、彈窗、表單組件會非??煸谛I鷮lement UI也比較熟悉遇到問題社區(qū)資料一搜就有。4.2 接口聯(lián)調(diào)時的三個經(jīng)典問題前后端聯(lián)調(diào)的時候有幾個問題幾乎每次都會遇到提前避坑能省出好幾天時間。第一個是跨域問題。前端項目跑在8080端口后端跑在8081端口瀏覽器直接請求后端接口會被攔截。解決辦法是后端寫一個配置類實現(xiàn)WebMvcConfigurer接口重寫addCorsMappings方法允許指定前端地址跨域訪問。注意如果用了JWT鑒權(quán)跨域配置里要允許自定義請求頭否則前端沒辦法把Token帶過去。第二個是時間格式問題。后端用LocalDateTime作為時間字段類型時通過默認(rèn)的JSON序列化前端拿到的是一長串?dāng)?shù)字?jǐn)?shù)組非常不直觀。解決辦法是在application.yml里統(tǒng)一配置時間格式化或者給實體類的時間字段加JsonFormat注解統(tǒng)一輸出為“yyyy-MM-dd HH:mm:ss”的字符串格式。第三個是null值問題。后端返回的數(shù)據(jù)里有些字段是null前端表格直接顯示“undefined”這個問題雖然不至于報錯但看起來很業(yè)余。建議統(tǒng)一Result封裝中集合類型返回空集合而不是null字符串類型返回空字符串或者由前端做兜底展示。4.3 驗收演示時的數(shù)據(jù)準(zhǔn)備技巧很多同學(xué)做畢業(yè)設(shè)計系統(tǒng)里的數(shù)據(jù)隨意亂填演示時打開頁面一片亂碼或內(nèi)容空洞給答辯老師的印象分直接掉一檔。數(shù)據(jù)準(zhǔn)備其實很簡單就是要“看起來像一個真實系統(tǒng)”。預(yù)置數(shù)據(jù)要做到課程名稱用真實的課程名高等數(shù)學(xué)、大學(xué)英語、數(shù)據(jù)結(jié)構(gòu)用戶姓名用自然的中文姓名組合成績分布盡量接近正態(tài)分布不要全是100分也不要全是60分。選課數(shù)據(jù)要體現(xiàn)“選滿”和“有空余”兩種狀態(tài)這樣演示選課功能時既能展示成功選課也方便觸發(fā)“課程已滿”的提示效果。這個小技巧在很多實際項目中驗證過花費半小時準(zhǔn)備數(shù)據(jù)答辯演示效果遠(yuǎn)勝于打開全是“test”字符串的系統(tǒng)。5. 常見問題與排查技巧實測中的避坑實錄5.1 列表查詢的N1問題成績列表頁是一個典型場景頁面要展示成績記錄每條記錄除了成績本身還要顯示學(xué)生姓名和課程名稱。如果初學(xué)階段圖省事在Service里循環(huán)查詢成績列表每遍歷一條記錄就查一次學(xué)生表、課程表這就會觸發(fā)N1查詢問題。假設(shè)成績表里有100條記錄至少要額外執(zhí)行200次查詢數(shù)據(jù)庫壓力大接口響應(yīng)慢頁面打開卡頓。解決思路很簡單不要循環(huán)查單表用一次關(guān)聯(lián)查詢把所有數(shù)據(jù)查出來。比如在Mapper里寫一個自定義SQL把成績表和學(xué)生表、開課表、課程表關(guān)聯(lián)起來返回一個帶學(xué)生姓名和課程名稱的視圖對象。MyBatis Plus提供的結(jié)果映射能支持這種自定義查詢但需要你手寫ResultMap這部分邏輯建議自己動手寫徹底理解關(guān)聯(lián)查詢的執(zhí)行過程。5.2 Transactional事務(wù)不生效的隱形坑事務(wù)不生效的幾個典型場景我在實際項目中都遇到過。第一種是同類內(nèi)部調(diào)用。比如在CourseService里有一個public方法選課方法內(nèi)調(diào)用了同一個類里另一個Transactional方法后者的事務(wù)不會生效。原因很簡單Spring的事務(wù)是通過代理對象實現(xiàn)的同類內(nèi)部調(diào)用走的是this對象而不是代理對象事務(wù)切面沒法攔截。解決辦法是避免同類調(diào)用把需要事務(wù)的子方法放到另一個Service類里或者直接在入口方法上加上事務(wù)注解。第二種是異常被catch了。事務(wù)方法執(zhí)行過程中內(nèi)部業(yè)務(wù)代碼如果自己try-catch吞掉了異常事務(wù)就不會回滾因為Spring根本感知不到異常發(fā)生。正確的做法是不要在需要回滾的事務(wù)方法內(nèi)吞掉異?;蛘卟东@后重新拋出RuntimeException。第三種是方法非public。Spring默認(rèn)的基于CGLIB或JDK代理的事務(wù)代理對非public方法是不會攔截的所以事務(wù)注解只能加在public方法上。5.3 MyBatis Plus邏輯刪除與自動填充的配置細(xì)節(jié)如果用了MyBatis Plus的邏輯刪除功能也就是配置了TableLogic注解需要注意兩點。第一實體類有了邏輯刪除字段后寫自定義SQL時如果不加is_deleted條件查出來的數(shù)據(jù)可能包含已經(jīng)標(biāo)記刪除的記錄。雖然MyBatis Plus自帶的queryWrapper會自動附加邏輯刪除條件但手寫SQL時需要自己記得帶上這個條件。第二邏輯刪除字段會影響分頁查詢的count語句這個一般MyBatis Plus已經(jīng)處理好了不用太擔(dān)心。自動填充功能也很實用在實體類創(chuàng)建時間和更新時間字段上加TableField(fill FieldFill.INSERT)或FieldFill.INSERT_UPDATE注解然后定義一個MetaObjectHandler實現(xiàn)類插入和更新記錄時自動填入當(dāng)前時間。這樣所有表的時間字段都不用手動維護(hù)代碼整潔度提升明顯。5.4 調(diào)試接口的實用工具組合隊伍里做后端調(diào)試一個趁手的接口測試工具效率遠(yuǎn)高于在瀏覽器里敲URL。我習(xí)慣用的組合是瀏覽器開發(fā)者工具查看接口請求響應(yīng)另一個桌面客戶端用來構(gòu)造各類測試請求。聯(lián)調(diào)階段構(gòu)造POST請求測試登錄接口、選課接口、成績錄入接口這些場景用桌面客戶端會比Postman更輕量操作也更順手。建議有空閑時把項目里所有接口按模塊整理一遍標(biāo)注清楚請求參數(shù)和返回示例這類接口文檔寫進(jìn)論文前面作為“系統(tǒng)接口設(shè)計”內(nèi)容非常扎實。6. 從功能完成到論文答辯最后一步怎么走答辯前建議把系統(tǒng)硬編碼的關(guān)鍵配置項比如選課時間的開啟和關(guān)閉狀態(tài)、課程容量的默認(rèn)值都做成可以在管理員頁面修改的配置項。這樣現(xiàn)場演示時可以直接操作開關(guān)不用臨時改代碼重新部署演示體驗會流暢很多。系統(tǒng)的用戶密碼存儲要使用加密算法不要在數(shù)據(jù)庫里存明文密碼這是答辯老師非常喜歡問的一個安全問題。使用Bcrypt或MD5加鹽都行推薦BCryptSpring Security自帶的支持比較完善。數(shù)據(jù)庫初始化腳本和預(yù)置數(shù)據(jù)腳本要一起放進(jìn)項目里答辯現(xiàn)場評委用自己的電腦跑項目時導(dǎo)入SQL后系統(tǒng)就應(yīng)該能直接運行。我在實際帶項目時還總結(jié)過一個規(guī)律答辯時與其緊張地演示所有功能不如圍繞一條核心鏈路講透從管理員創(chuàng)建開課到學(xué)生選課到教師錄成績再到學(xué)生查成績前后端數(shù)據(jù)和狀態(tài)的變化要能對上。能把這個閉環(huán)清晰展示出來的同學(xué)答辯分?jǐn)?shù)都不會低。這條鏈路同時也是論文里系統(tǒng)測試章節(jié)的測試用例設(shè)計基礎(chǔ)功能測試、權(quán)限測試、并發(fā)測試都能從這里面衍生出來。最后分享一個個人體會做教務(wù)管理系統(tǒng)這類項目技術(shù)上沒有任何一個點屬于“天頂星難度”難點全在于把大量簡單的功能流程做得嚴(yán)謹(jǐn)可靠。你認(rèn)真處理了選課并發(fā)、權(quán)限校驗、事務(wù)邊界這些細(xì)節(jié)你會發(fā)現(xiàn)寫論文時的技術(shù)難點部分根本不用編因為每一個坑都是真實踩出來的。這些踩坑經(jīng)驗才是畢業(yè)設(shè)計能帶給你的最大收獲。