設(shè)計(jì)與Spring Boot實(shí)現(xiàn):從預(yù)約到測(cè)評(píng)全解析)
如果你正在準(zhǔn)備Java方向的畢業(yè)設(shè)計(jì)大概率會(huì)碰到這類題目高校大學(xué)生心理咨詢管理系統(tǒng)。我第一次拿到這套題目時(shí)覺(jué)得“又是一個(gè)CRUD項(xiàng)目”但真正把基于Spring Boot的源碼完整跑通、拆完模塊之后我發(fā)現(xiàn)它比想象中更值得做。用戶角色有三類業(yè)務(wù)流里有預(yù)約排期、問(wèn)卷測(cè)評(píng)、狀態(tài)流轉(zhuǎn)、統(tǒng)計(jì)報(bào)表后端正好用得上Spring Boot、MyBatis、MySQL、Maven這一套Java開(kāi)發(fā)最主流的技術(shù)。無(wú)論你是想快速交差還是想在答辯時(shí)多講幾句設(shè)計(jì)思路這套系統(tǒng)的源碼、文檔、運(yùn)行視頻和講解視頻都能提供一條完整的可復(fù)現(xiàn)路徑。先說(shuō)一下這套交付物怎么搭配使用。很多人拿到壓縮包第一件事就是解壓導(dǎo)入IDEA結(jié)果依賴報(bào)錯(cuò)、數(shù)據(jù)庫(kù)就連不上心態(tài)直接崩。我的建議是嚴(yán)格按“運(yùn)行視頻 → 文檔 → 源碼 → 講解視頻”的順序來(lái)。運(yùn)行視頻先讓你看到系統(tǒng)最終長(zhǎng)什么樣知道目標(biāo)文檔幫你理解需求和技術(shù)選型節(jié)省自己猜架構(gòu)的時(shí)間源碼用來(lái)逐模塊對(duì)照細(xì)節(jié)講解視頻則是在你卡住的時(shí)候聽(tīng)對(duì)方把關(guān)鍵邏輯從頭串一遍。按這個(gè)順序走能避開(kāi)一半的無(wú)頭緒問(wèn)題。1. 心理咨詢管理系統(tǒng)到底做給誰(shuí)用1.1 業(yè)務(wù)痛點(diǎn)決定功能邊界高校心理咨詢這個(gè)場(chǎng)景表面看就是“學(xué)生預(yù)約老師做咨詢”但實(shí)際管理起來(lái)有不少麻煩。傳統(tǒng)方式是線下填表、QQ通知、Excel排期咨詢師很難掌握自己的空閑時(shí)段學(xué)生預(yù)約后也容易因?yàn)樾畔⒉煌蕉s咨詢記錄散落在各個(gè)老師手里學(xué)院想統(tǒng)計(jì)一下“這學(xué)期咨詢了哪些類型的問(wèn)題”都很費(fèi)勁。這套系統(tǒng)的價(jià)值就是把上面這些動(dòng)作搬到線上學(xué)生注冊(cè)登錄后查看咨詢師排班、發(fā)起預(yù)約、填寫(xiě)心理測(cè)評(píng)問(wèn)卷咨詢師維護(hù)自己的可預(yù)約時(shí)間、查看預(yù)約列表、填寫(xiě)咨詢記錄管理員管理教師賬號(hào)、發(fā)布心理健康文章、查看統(tǒng)計(jì)面板。整個(gè)流程形成了閉環(huán)數(shù)據(jù)都沉淀在數(shù)據(jù)庫(kù)里隨時(shí)可以導(dǎo)出和統(tǒng)計(jì)。1.2 為什么說(shuō)這個(gè)題目是“踩分題”畢業(yè)設(shè)計(jì)答辯時(shí)評(píng)委最看重的是“你解決了一個(gè)什么問(wèn)題技術(shù)選型是否合理核心功能能否演示”。心理咨詢管理系統(tǒng)恰好把這三個(gè)點(diǎn)全占了。業(yè)務(wù)上它有明確的角色邊界和狀態(tài)流轉(zhuǎn)比如“待確認(rèn) → 已預(yù)約 → 已完成 → 已取消”這種狀態(tài)機(jī)非常適合做業(yè)務(wù)邏輯分析。技術(shù)上它能覆蓋SSM/Spring Boot開(kāi)發(fā)的主要環(huán)節(jié)登錄鑒權(quán)、增刪改查、分頁(yè)搜索、文件上傳、圖表統(tǒng)計(jì)、預(yù)約排期去重。數(shù)據(jù)上它天然包含用戶、預(yù)約、測(cè)評(píng)、記錄、文章五類核心實(shí)體表關(guān)系清晰畫(huà)ER圖也容易。所以這不是一個(gè)拿不出手的水項(xiàng)目而是能讓你在答辯時(shí)講足十分鐘的“六邊形戰(zhàn)士”題目。2. 系統(tǒng)整體設(shè)計(jì)先把角色和模塊畫(huà)清楚2.1 三種角色與權(quán)限邊界拿到源碼后我強(qiáng)烈建議你先打開(kāi)文檔里的“系統(tǒng)功能結(jié)構(gòu)圖”對(duì)照著再畫(huà)一遍自己心里的權(quán)限邊界。這個(gè)系統(tǒng)有三種角色學(xué)生注冊(cè)、登錄、瀏覽咨詢師信息、創(chuàng)建預(yù)約、取消預(yù)約、填寫(xiě)心理測(cè)評(píng)問(wèn)卷、查看自己的測(cè)評(píng)報(bào)告。咨詢師登錄、維護(hù)排班計(jì)劃、處理預(yù)約請(qǐng)求、填寫(xiě)咨詢記錄、查看學(xué)生基本信息。管理員管理學(xué)生和咨詢師賬號(hào)、審核咨詢師排班、管理公告和心理健康文章、查看系統(tǒng)統(tǒng)計(jì)數(shù)據(jù)。不要小看這個(gè)簡(jiǎn)單的角色劃分。很多同學(xué)的代碼里所有Controller都是同一個(gè)權(quán)限連“學(xué)生不能訪問(wèn)管理員接口”這種最基本的隔離都做不到。而一套合格的畢設(shè)源碼應(yīng)該是通過(guò)攔截器或Spring Security做角色判斷的。你拿到源碼后第一件事就是去Controller層搜索每個(gè)RequestMapping確認(rèn)哪些接口加了角色校驗(yàn)這在答辯時(shí)非常加分。2.2 功能模塊地圖按后端的物理分層來(lái)看系統(tǒng)一般拆成這幾個(gè)模塊模塊核心功能涉及的表用戶模塊登錄、注冊(cè)、密碼加密、個(gè)人信息維護(hù)student / counselor / admin預(yù)約模塊排班維護(hù)、預(yù)約創(chuàng)建、取消、狀態(tài)流轉(zhuǎn)schedule / appointment咨詢模塊咨詢記錄填寫(xiě)、查看consult_record測(cè)評(píng)模塊問(wèn)卷管理、測(cè)評(píng)提交、分?jǐn)?shù)計(jì)算、報(bào)告生成assessment / questionnaire / answer資訊模塊心理文章發(fā)布、展示article統(tǒng)計(jì)模塊各圖表數(shù)據(jù)聚合基于預(yù)約表和測(cè)評(píng)表統(tǒng)計(jì)我自己的習(xí)慣是先用這個(gè)模塊地圖把源碼目錄過(guò)一遍。如果源碼里包結(jié)構(gòu)清晰比如controller/service/mapper/entity/vo各層分明那整個(gè)項(xiàng)目基本就沒(méi)什么看不懂的了。如果遇到包路徑混亂的項(xiàng)目就按Controller → Service → Mapper往下追一條鏈路讀懂再換下一條。2.3 我對(duì)模塊拆分的順序建議我不建議你從登錄開(kāi)始看源碼。登錄鑒權(quán)涉及的邏輯雖然不復(fù)雜但攔截器、全局異常、JWT過(guò)濾器都堆在一起很容易讓人陷入細(xì)節(jié)。我建議先從預(yù)約模塊看起因?yàn)轭A(yù)約是這個(gè)系統(tǒng)的業(yè)務(wù)核心它連接了學(xué)生、咨詢師、排班、狀態(tài)四個(gè)維度看懂預(yù)約整個(gè)系統(tǒng)的數(shù)據(jù)流就通了一半。然后是測(cè)評(píng)模塊。測(cè)評(píng)模塊里有問(wèn)卷題目、用戶答案、分?jǐn)?shù)計(jì)算這三塊業(yè)務(wù)邏輯最濃答辯時(shí)也最容易拿出來(lái)講。最后再看管理員的后臺(tái)統(tǒng)計(jì)因?yàn)樗皇菍?duì)前面業(yè)務(wù)的SQL聚合本質(zhì)上是錦上添花。3. 技術(shù)棧與項(xiàng)目結(jié)構(gòu)解析3.1 核心依賴與版本選擇這套系統(tǒng)的基礎(chǔ)設(shè)施通常是Spring Boot作為應(yīng)用框架MyBatis作為ORM層MySQL作為數(shù)據(jù)庫(kù)Maven作為構(gòu)建工具。有些版本會(huì)采用Spring Boot 2.x搭配MyBatis有些可能會(huì)用Spring Boot 3.x配合MyBatis Plus。如果是畢業(yè)設(shè)計(jì)我個(gè)人更推薦Spring Boot 2.7.x MyBatis的組合原因很實(shí)際。Spring Boot 2.7生態(tài)非常成熟網(wǎng)上教程最多遇到問(wèn)題搜索容易找到答案。Spring Boot 3.0起要求JDK 17雖然新但很多老教程里的javax命名空間要改成jakarta光這一點(diǎn)就能卡住一大片新手。如果你的JDK是1.8那就踏踏實(shí)實(shí)用Spring Boot 2.7如果你的環(huán)境已經(jīng)是JDK 17并且你愿意踩一遍遷移的坑再考慮3.x。源碼里如果帶了pom.xml先看parent里的版本心里有數(shù)再動(dòng)手。3.2 項(xiàng)目目錄結(jié)構(gòu)一套規(guī)范的Spring Boot項(xiàng)目目錄長(zhǎng)得像這樣src/main/java ├── com.example.psych │ ├── controller │ │ ├── StudentController.java │ │ ├── CounselorController.java │ │ └── AdminController.java │ ├── service │ │ └── impl │ ├── mapper │ ├── entity │ ├── vo │ ├── config │ │ ├── WebConfig.java │ │ └── InterceptorConfig.java │ ├── common │ │ ├── Result.java │ │ └── GlobalExceptionHandler.java │ └── PsychApplication.java src/main/resources ├── application.yml ├── mapper │ ├── StudentMapper.xml │ ├── AppointmentMapper.xml │ └── ... ├── sql │ └── psych.sql └── static / templates我之所以覺(jué)得目錄結(jié)構(gòu)重要是因?yàn)楹芏嗤瑢W(xué)導(dǎo)入源碼后找不到啟動(dòng)類找不到配置文件。如果你拿到手的源碼符合上面這個(gè)結(jié)構(gòu)那基本就是標(biāo)準(zhǔn)工程。Result.java是統(tǒng)一返回體一般包含code、message、data三個(gè)字段GlobalExceptionHandler是全局異常處理負(fù)責(zé)把業(yè)務(wù)異常轉(zhuǎn)成友好的提示。這兩個(gè)類在答辯時(shí)一定要能講清楚因?yàn)樗鼈兪恰肮こ袒钡捏w現(xiàn)。3.3 為什么用MyBatis而不是JPA這個(gè)問(wèn)題幾乎每次答辯都會(huì)被問(wèn)到。我的理解是MyBatis的SQL都是自己寫(xiě)的可控性強(qiáng)一個(gè)復(fù)雜的統(tǒng)計(jì)SQL可以直接寫(xiě)死在Mapper XML里出了問(wèn)題你能精準(zhǔn)定位JPA/Hibernate雖然省事但自動(dòng)生成的SQL對(duì)很多學(xué)生來(lái)說(shuō)是個(gè)黑盒一旦性能有問(wèn)題或者關(guān)聯(lián)查詢報(bào)錯(cuò)排查起來(lái)非常痛苦。心理咨詢系統(tǒng)里的統(tǒng)計(jì)報(bào)表比如“近半年每月預(yù)約人數(shù)”“不同測(cè)評(píng)分?jǐn)?shù)段人數(shù)分布”用MyBatis寫(xiě)自定義SQL非常直觀SELECT DATE_FORMAT(create_time, %Y-%m) AS month, COUNT(*) AS cnt FROM appointment WHERE status 已完成 GROUP BY DATE_FORMAT(create_time, %Y-%m) ORDER BY month;這種SQL在Mapper XML里寫(xiě)完之后Service層直接調(diào)用邏輯清清楚楚。答辯時(shí)你可以說(shuō)“我選擇MyBatis是為了保證復(fù)雜查詢可控自定義SQL可以貼合業(yè)務(wù)做優(yōu)化?!边@句話一講評(píng)委就知道你不是只會(huì)調(diào)用框架的。4. 數(shù)據(jù)庫(kù)設(shè)計(jì)五張核心表理清關(guān)系4.1 用戶表與角色設(shè)計(jì)心理咨詢系統(tǒng)的數(shù)據(jù)庫(kù)設(shè)計(jì)比一般純CRUD項(xiàng)目要細(xì)致一些。我拆完這套源碼之后發(fā)現(xiàn)它把“用戶”拆成了兩張表學(xué)生表和咨詢師表而不是共用一張user表加role字段。這種設(shè)計(jì)的理由是業(yè)務(wù)字段差異大學(xué)生需要學(xué)號(hào)、學(xué)院、班級(jí)咨詢師需要工號(hào)、職稱、擅長(zhǎng)領(lǐng)域。如果強(qiáng)行合并成一張表會(huì)有一堆字段在某種角色下永遠(yuǎn)為空非常零散。如果你拿到的源碼恰好是用單用戶表加role字段的寫(xiě)法也不要慌答辯時(shí)可以說(shuō)“我用一張user表統(tǒng)一鑒權(quán)通過(guò)role區(qū)分權(quán)限考慮到未來(lái)擴(kuò)展也可以拆分為子表”。兩種方案都有講法關(guān)鍵是你能自圓其說(shuō)并且理解自己項(xiàng)目里的取舍。4.2 咨詢預(yù)約表與狀態(tài)流轉(zhuǎn)預(yù)約表是整個(gè)系統(tǒng)的核心表字段一般有CREATE TABLE appointment ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_id BIGINT NOT NULL COMMENT 學(xué)生ID, schedule_id BIGINT NOT NULL COMMENT 排班ID, counselor_id BIGINT NOT NULL COMMENT 咨詢師ID, appoint_date DATE NOT NULL COMMENT 預(yù)約日期, start_time TIME NOT NULL COMMENT 開(kāi)始時(shí)間, end_time TIME NOT NULL COMMENT 結(jié)束時(shí)間, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待確認(rèn) 1已確認(rèn) 2已完成 3已取消, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, remark VARCHAR(255) );這張表最值得講的點(diǎn)是狀態(tài)流轉(zhuǎn)。學(xué)生創(chuàng)建預(yù)約后狀態(tài)是“待確認(rèn)”咨詢師確認(rèn)后才變成“已確認(rèn)”咨詢完成之后置為“已完成”學(xué)生在預(yù)約開(kāi)始前可以取消但取消后該時(shí)段應(yīng)該釋放重新變成可預(yù)約。這個(gè)狀態(tài)機(jī)的約束條件在Service層要寫(xiě)清楚。很多項(xiàng)目死鎖或者Bug都出在“狀態(tài)該更新時(shí)沒(méi)更新不該更新時(shí)亂更新”。4.3 心理測(cè)評(píng)問(wèn)卷表的設(shè)計(jì)思路心理測(cè)評(píng)表通常是兩到三張問(wèn)卷表questionnaire、題目表question、答案記錄表user_answer和測(cè)評(píng)結(jié)果表assessment_result。題目表與問(wèn)卷表是多對(duì)一關(guān)系答案記錄表與預(yù)約或用戶關(guān)聯(lián)。設(shè)計(jì)上有個(gè)容易忽視的地方題目選項(xiàng)的分?jǐn)?shù)要提前設(shè)計(jì)好比如“幾乎沒(méi)有0分偶爾1分經(jīng)常2分總是3分”然后根據(jù)總分映射到不同建議區(qū)間。這部分在源碼里通常不是簡(jiǎn)單的CRUD而是有業(yè)務(wù)邏輯的。答辯時(shí)可以把這個(gè)算法單獨(dú)講三分鐘比講十個(gè)增刪改查都強(qiáng)。我見(jiàn)過(guò)一個(gè)不錯(cuò)的實(shí)現(xiàn)是先根據(jù)問(wèn)卷ID查出所有題目再遍歷用戶提交的答案列表計(jì)算總分最后根據(jù)總分閾值生成測(cè)評(píng)報(bào)告和建議文案。整個(gè)計(jì)算過(guò)程放在Service事務(wù)里保證答案和結(jié)果表的寫(xiě)入要么都成功要么都回滾。5. 核心功能實(shí)現(xiàn)從登錄到預(yù)約全鏈路5.1 登錄鑒權(quán)Session還是JWT心理咨詢管理系統(tǒng)的登錄實(shí)現(xiàn)一般有兩種用Session攔截器或者用JWTToken過(guò)濾器。如果你拿到的是JWT版本那演示起來(lái)會(huì)更像企業(yè)級(jí)項(xiàng)目。核心流程是用戶登錄成功后服務(wù)端簽發(fā)一個(gè)Token前端每次請(qǐng)求都把它放到Header里后端攔截器校驗(yàn)Token并把用戶信息放進(jìn)ThreadLocal。這套流程不算復(fù)雜但覆蓋面廣很能體現(xiàn)你對(duì)Web開(kāi)發(fā)的理解。對(duì)應(yīng)源碼里通常會(huì)有兩個(gè)關(guān)鍵類JwtUtil負(fù)責(zé)生成和解析TokenAuthInterceptor負(fù)責(zé)攔截請(qǐng)求并校驗(yàn)Token。你只需要記住幾點(diǎn)Token要設(shè)過(guò)期時(shí)間攔截器要排除登錄和注冊(cè)接口密碼要加鹽加密別用明文。答辯時(shí)被問(wèn)到“如何保證接口安全”這三點(diǎn)直接回答評(píng)委基本滿意。5.2 咨詢師排班與預(yù)約沖突處理這是整個(gè)系統(tǒng)最有技術(shù)含量的一塊業(yè)務(wù)。咨詢師先創(chuàng)建一周的排班表每一條記錄是一個(gè)時(shí)間段比如“周二 14:00-15:00”。學(xué)生預(yù)約時(shí)系統(tǒng)必須保證這個(gè)時(shí)間段沒(méi)有被其他人預(yù)約同時(shí)學(xué)生自己一天只能約一次。代碼邏輯一般是在預(yù)約前先查詢boolean conflict appointmentService.hasConflict(studentId, scheduleId, appointDate, startTime, endTime); if (conflict) { throw new BizException(該時(shí)間段已被預(yù)約請(qǐng)選擇其他時(shí)間); }hasConflict對(duì)應(yīng)的SQL大概是SELECT COUNT(*) FROM appointment WHERE schedule_id #{scheduleId} AND appoint_date #{appointDate} AND status IN (0, 1) AND ( (start_time #{endTime} AND end_time #{startTime}) )這條SQL里的重點(diǎn)不是排重而是“狀態(tài)只能查待確認(rèn)和已確認(rèn)”如果已經(jīng)是“已完成”或“已取消”就不算占用時(shí)間。我剛接觸這套代碼的時(shí)候在這個(gè)狀態(tài)過(guò)濾上踩過(guò)坑一度讓用戶無(wú)法重復(fù)預(yù)約已經(jīng)完成的時(shí)間段。這種細(xì)節(jié)就是你在答辯時(shí)最值得拿出來(lái)講的“我考慮了”。5.3 測(cè)評(píng)模塊的分?jǐn)?shù)計(jì)算與建議輸出測(cè)評(píng)模塊的代碼值得單獨(dú)看。它要處理的不只是保存答案還要根據(jù)答題情況算總分。常見(jiàn)實(shí)現(xiàn)是前端提交一個(gè)MapquestionId, optionScore集合。Service層根據(jù)questionId查出對(duì)應(yīng)問(wèn)卷ID循環(huán)累加分?jǐn)?shù)。根據(jù)總分所在區(qū)間生成不同等級(jí)評(píng)價(jià)。將總分?jǐn)?shù)、等級(jí)、建議文案插入assessment_result表。這個(gè)流程雖然看起來(lái)簡(jiǎn)單但有兩個(gè)坑。一是題目ID和問(wèn)卷ID不匹配時(shí)會(huì)查出空數(shù)據(jù)一定要在循環(huán)里做空值判斷。二是總分計(jì)算要考慮反向計(jì)分的題目比如某些題目分?jǐn)?shù)越高表示狀態(tài)越差有些則相反。如果你的源碼里沒(méi)有處理反向計(jì)分可以在擴(kuò)展點(diǎn)里提出來(lái)作為后期優(yōu)化的方向。5.4 統(tǒng)計(jì)看板的SQL聚合管理員界面一般會(huì)展示餅圖和柱狀圖這些數(shù)據(jù)來(lái)自聚合SQL。比如按學(xué)院統(tǒng)計(jì)咨詢?nèi)藬?shù)SELECT s.college, COUNT(DISTINCT a.id) AS cnt FROM appointment a JOIN student s ON a.student_id s.id WHERE a.status 已完成 GROUP BY s.college;需要留意COUNT(DISTINCT a.id)而不是COUNT(*)因?yàn)橐粋€(gè)學(xué)生可能完成多次咨詢按學(xué)院統(tǒng)計(jì)“人數(shù)”時(shí)必須去重。源碼里如果在這個(gè)地方直接用了COUNT(*)統(tǒng)計(jì)數(shù)字會(huì)偏大。答辯時(shí)你能指出這個(gè)問(wèn)題并且當(dāng)場(chǎng)改掉效果拉滿。6. 導(dǎo)入源碼、改配置、跑起來(lái)的完整流程6.1 本地環(huán)境準(zhǔn)備如果你拿到的是源碼加視頻我建議先按下面這個(gè)環(huán)境清單核對(duì)JDK 1.8或11看pom.xml依賴要求Maven 3.6MySQL 5.7或8.0IDEA 2020以上環(huán)境不對(duì)是最常見(jiàn)的問(wèn)題。有人用JDK 17跑Spring Boot 2.5會(huì)報(bào)錯(cuò)有人MySQL 8的密文鏈接配置和5.7不一樣。視頻里如果提到“把SQL文件導(dǎo)入Navicat執(zhí)行”那說(shuō)明數(shù)據(jù)庫(kù)連接是簡(jiǎn)單的root賬號(hào)。自己本地環(huán)境如果改了密碼記得同步修改application.yml。6.2 修改關(guān)鍵配置在application.yml里最需要改的就是數(shù)據(jù)庫(kù)連接spring: datasource: url: jdbc:mysql://localhost:3306/psych_system?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8 server: port: 8080這里有幾個(gè)坑serverTimezone一定要加MySQL 8不加會(huì)報(bào)“無(wú)法識(shí)別時(shí)區(qū)”useSSLfalse是為了防止本地沒(méi)有證書(shū)時(shí)報(bào)錯(cuò)端口如果被占用改成8081或者9090。我自己第一次運(yùn)行這套系統(tǒng)時(shí)就是漏了serverTimezone一直報(bào)數(shù)據(jù)庫(kù)連接超時(shí)折騰了半小時(shí)才發(fā)現(xiàn)。6.3 項(xiàng)目啟動(dòng)順序?qū)腠?xiàng)目后先打開(kāi)數(shù)據(jù)庫(kù)管理工具執(zhí)行sql/psych.sql再啟動(dòng)PsychApplication.java。啟動(dòng)成功后訪問(wèn)http://localhost:8080用文檔里寫(xiě)好的測(cè)試賬號(hào)登錄。如果你發(fā)現(xiàn)頁(yè)面顯示不出來(lái)優(yōu)先查看IDEA控制臺(tái)日志看端口有沒(méi)有被占、數(shù)據(jù)庫(kù)連沒(méi)連上、MyBatis的Mapper映射有沒(méi)有綁定。運(yùn)行視頻一般會(huì)把完整效果跑一遍你可以對(duì)照著自己的界面逐步確認(rèn)是否一致。這一步做完整套系統(tǒng)就已經(jīng)在你的機(jī)器上活了。7. 我踩過(guò)的坑運(yùn)行和答辯瞬間的高頻問(wèn)題7.1 分頁(yè)查詢失效很多源碼里用的是PageHelper或者M(jìn)yBatis Plus分頁(yè)。如果查詢結(jié)果沒(méi)有分頁(yè)多半是依賴沒(méi)配好或者調(diào)用方式不對(duì)。PageHelper必須在緊挨著要分頁(yè)的查詢前調(diào)用不能中間隔了其他操作否則分頁(yè)會(huì)作用到錯(cuò)誤的SQL上。我之前幫學(xué)生改這套系統(tǒng)時(shí)遇到過(guò)一個(gè)場(chǎng)景Service層先查了咨詢師信息再查詢預(yù)約列表PageHelper.startPage寫(xiě)在查詢咨詢師之前結(jié)果分頁(yè)未生效列表全部數(shù)據(jù)一次性返回。排查了很久才意識(shí)到是調(diào)用順序問(wèn)題。所以如果你發(fā)現(xiàn)分頁(yè)失效第一件事就是看startPage和selectList之間有沒(méi)有插入其他查詢。7.2 預(yù)約時(shí)間重復(fù)仍能提交這種情況通常是前端提交時(shí)沒(méi)有把時(shí)間參數(shù)傳完整或者后端沖突SQL里的狀態(tài)條件寫(xiě)錯(cuò)。把預(yù)約字段打印出來(lái)對(duì)照SQL條件檢查如果還是能通過(guò)就用數(shù)據(jù)庫(kù)直接執(zhí)行沖突SQL看看有沒(méi)有返回記錄。很多時(shí)候是時(shí)間字段類型不匹配Java的LocalTime傳到MySQL被截?cái)鄬?dǎo)致邊界值重合。解決方法是改SQL比較把startTime和endTime統(tǒng)一轉(zhuǎn)成字符串格式或者干脆在Java層先做時(shí)間重疊判斷再入庫(kù)。7.3 講解視頻到底怎么看這套交付物里最容易被忽略的就是講解視頻。很多人覺(jué)得跑起來(lái)了就足夠了視頻放著不看。我的建議是視頻至少要看兩遍。第一遍倍速過(guò)了解講課人的表達(dá)節(jié)奏第二遍在你準(zhǔn)備答辯時(shí)看重點(diǎn)聽(tīng)核心模塊的講解思路。在答辯時(shí)你不需要把整個(gè)項(xiàng)目的每個(gè)功能都講到評(píng)委想聽(tīng)的是你對(duì)關(guān)鍵模塊的理解。視頻里通常會(huì)把登錄鑒權(quán)、預(yù)約狀態(tài)流轉(zhuǎn)、測(cè)評(píng)分?jǐn)?shù)計(jì)算拆開(kāi)講這些正是評(píng)委愛(ài)問(wèn)的部分。你把視頻里的講解邏輯吃透用自己的話復(fù)述一遍比背源碼強(qiáng)得多。7.4 論文里的技術(shù)圖別照抄文檔中一般會(huì)包含系統(tǒng)架構(gòu)圖、功能結(jié)構(gòu)圖、E-R圖。如果你要寫(xiě)論文千萬(wàn)不要直接截圖粘貼。好多學(xué)校的查重和格式審核會(huì)識(shí)別圖片中的文字照抄有風(fēng)險(xiǎn)。正確的做法是理解圖里的層級(jí)關(guān)系用Visio或ProcessOn重新畫(huà)一遍換成自己的配色和表達(dá)方式。圖畫(huà)完你對(duì)系統(tǒng)的理解也會(huì)更深一層。8. 如何把項(xiàng)目講得比源碼本身更出彩8.1 答辯講解節(jié)奏答辯時(shí)間普遍只有五到十分鐘別一上來(lái)就講需求背景那是在浪費(fèi)全場(chǎng)的耐心。我的建議是三段式先講痛點(diǎn)再講技術(shù)方案最后現(xiàn)場(chǎng)演示核心頁(yè)面。痛點(diǎn)用一句話概括高校心理咨詢預(yù)約靠人工容易沖突且沒(méi)有數(shù)據(jù)沉淀。技術(shù)方案用一張技術(shù)棧表帶過(guò)Spring Boot提供基礎(chǔ)框架MyBatis管理SQLMySQL存儲(chǔ)業(yè)務(wù)數(shù)據(jù)然后引出你最熟悉的核心功能。演示時(shí)先從學(xué)生預(yù)約開(kāi)始當(dāng)場(chǎng)創(chuàng)建一個(gè)預(yù)約再到咨詢師端確認(rèn)預(yù)約最后去管理員后臺(tái)看統(tǒng)計(jì)數(shù)據(jù)變化。這一套鏈路走下來(lái)評(píng)委已經(jīng)心里有數(shù)。8.2 三個(gè)可以主動(dòng)加分的擴(kuò)展點(diǎn)如果評(píng)委問(wèn)“你還有什么可以改進(jìn)的地方”千萬(wàn)不要說(shuō)“沒(méi)有”。提前準(zhǔn)備三個(gè)擴(kuò)展點(diǎn)會(huì)讓你的收尾非常漂亮。第一個(gè)是引入Spring Security或Sa-Token做更精細(xì)的權(quán)限控制替代簡(jiǎn)單的攔截器校驗(yàn)。第二個(gè)是用Redis緩存咨詢師排班數(shù)據(jù)預(yù)約時(shí)直接在緩存里判斷沖突減少數(shù)據(jù)庫(kù)壓力。第三個(gè)是增加消息通知預(yù)約狀態(tài)變化時(shí)通過(guò)WebSocket推送給學(xué)生避免學(xué)生反復(fù)刷新頁(yè)面。這三個(gè)擴(kuò)展點(diǎn)都建立在現(xiàn)有代碼之上不用實(shí)際實(shí)現(xiàn)只要你講得清思路就能體現(xiàn)你的系統(tǒng)思考能力?;氐竭@套題本身我個(gè)人覺(jué)得它最難得的地方不是代碼多復(fù)雜而是它把一套完整業(yè)務(wù)串了起來(lái)讓你在畢業(yè)設(shè)計(jì)階段就能體驗(yàn)到一個(gè)“真實(shí)系統(tǒng)”從設(shè)計(jì)到落地的全過(guò)程。如果你手里已經(jīng)有了源碼和視頻不要囤著按照我上面的順序拆一遍把預(yù)約和測(cè)評(píng)這兩個(gè)核心鏈路親手畫(huà)出來(lái)、跑通、講明白這個(gè)項(xiàng)目就真正變成你自己的東西了。最后再提醒一句答辯時(shí)自信一點(diǎn)你掌握的每一個(gè)實(shí)現(xiàn)細(xì)節(jié)都比一句“我用了Spring Boot”有分量得多。