生宿舍管理系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)全復(fù)盤)
1. 這個(gè)系統(tǒng)為什么年年有人做年年有人喊難每到了課程設(shè)計(jì)和畢業(yè)設(shè)計(jì)的季節(jié)技術(shù)社區(qū)里就會(huì)出現(xiàn)大量求學(xué)生宿舍管理系統(tǒng)源碼的帖子。說實(shí)話這道題看起來簡(jiǎn)單和做起來麻煩的落差比想象中要大得多。表面上看就是幾個(gè)增刪改查頁(yè)面學(xué)生信息、宿舍信息、報(bào)修記錄。但真正動(dòng)手做的時(shí)候權(quán)限怎么劃分、床位狀態(tài)怎么流轉(zhuǎn)、同一個(gè)床位會(huì)不會(huì)被兩個(gè)人同時(shí)選中、統(tǒng)計(jì)報(bào)表里的數(shù)字怎么算才說得清這些細(xì)節(jié)會(huì)把一個(gè)簡(jiǎn)單系統(tǒng)硬生生拖成日夜趕工項(xiàng)目。我去年幫一個(gè)朋友完整做了一套基于SpringBoot和Vue的學(xué)生宿舍管理系統(tǒng)從數(shù)據(jù)庫(kù)設(shè)計(jì)到前端頁(yè)面再到部署上線前后搭進(jìn)去一個(gè)周末加幾個(gè)晚上。這篇文章就把整個(gè)開發(fā)過程中的決策邏輯、踩坑點(diǎn)和最終方案完整復(fù)盤一遍。不涉及具體商業(yè)代碼但每一個(gè)設(shè)計(jì)思路和實(shí)現(xiàn)方案你都可以直接復(fù)制到自己的項(xiàng)目里。適合正在做課設(shè)或畢設(shè)、想從能跑進(jìn)化到能講的同學(xué)也適合剛接觸前后端分離架構(gòu)、想找一個(gè)完整案例練手的開發(fā)者。1.1 一份需求清單先搞清楚宿舍管理系統(tǒng)到底管什么在動(dòng)手寫代碼之前我習(xí)慣先把需求掰開揉碎。學(xué)生宿舍管理系統(tǒng)通常涉及三類角色系統(tǒng)管理員、宿管員、學(xué)生。以最常見的課設(shè)要求為例核心功能基本跑不出這幾個(gè)模塊基礎(chǔ)信息管理樓棟管理、宿舍管理、床位管理、學(xué)生信息錄入與維護(hù)。宿舍分配業(yè)務(wù)學(xué)生入住分配床位、退宿釋放床位、調(diào)宿申請(qǐng)與審批。日常事務(wù)管理衛(wèi)生檢查打分、報(bào)修登記與處理進(jìn)度、晚歸或請(qǐng)假登記。查詢與統(tǒng)計(jì)按樓棟、學(xué)院、班級(jí)查學(xué)生統(tǒng)計(jì)入住率、報(bào)修處理率等。系統(tǒng)管理賬號(hào)管理、角色權(quán)限控制、密碼修改、登錄日志。這里有一個(gè)非常重要的認(rèn)知這些功能里真正有技術(shù)含量的不是增刪改查而是床位的狀態(tài)流轉(zhuǎn)和權(quán)限控制。床位不是簡(jiǎn)單的一個(gè)字段它有空閑、已入住、維修中三種狀態(tài)而且同一個(gè)學(xué)生不能同時(shí)占兩個(gè)床位兩個(gè)管理員也不能同時(shí)把同一個(gè)床位分給不同的人。如果不提前設(shè)計(jì)好數(shù)據(jù)模型和更新邏輯后面做分配功能時(shí)會(huì)不停地返工。1.2 這篇博文的定位不是源碼搬運(yùn)而是設(shè)計(jì)思路的完整復(fù)盤我清楚很多人搜學(xué)生宿舍管理系統(tǒng)源碼就是想要一份能直接交差的東西。但我更建議你把這篇內(nèi)容當(dāng)成設(shè)計(jì)文檔級(jí)別的實(shí)戰(zhàn)筆記來看。我會(huì)詳細(xì)說明為什么選SpringBoot而不選SSM數(shù)據(jù)庫(kù)表為什么要那樣建用戶登錄的token到底是怎么流轉(zhuǎn)的前端打包之后怎么丟進(jìn)SpringBoot的靜態(tài)目錄里以及哪幾個(gè)位置最容易在答辯現(xiàn)場(chǎng)被老師一句話問住。就算你最后不用我這里的方案沿著這套思路去拆解任何一份開源源碼你也能在很短時(shí)間內(nèi)看懂它、改進(jìn)它并寫好配套文檔。下面進(jìn)入正題。2. 翻開一份能跑的源碼SpringBootVue的骨架到底長(zhǎng)啥樣我見過太多課設(shè)項(xiàng)目前端是一個(gè)HTML頁(yè)面套著一堆jQuery后端是Servlet加JDBC代碼全堆在Controller里。能跑但答辯老師只要問一句如果并發(fā)50個(gè)人同時(shí)選床位怎么辦基本就卡殼了。用SpringBoot加Vue做前后端分離不是為了趕潮流而是這兩個(gè)框架恰好都滿足課設(shè)場(chǎng)景里最重要的三個(gè)要求學(xué)習(xí)成本可控、資料足夠多、架構(gòu)經(jīng)得起追問。2.1 前后端分離的本質(zhì)兩個(gè)項(xiàng)目還是一個(gè)項(xiàng)目先把這個(gè)問題講透。前后端分離在物理上通常是兩個(gè)獨(dú)立的工程一個(gè)是SpringBoot的Maven工程一個(gè)是用Vue CLI或Vite創(chuàng)建的Node前端工程。后端只提供HTTP接口、返回JSON前端只管渲染頁(yè)面和交互二者通過Axios之類的HTTP客戶端通信。一個(gè)標(biāo)準(zhǔn)的目錄結(jié)構(gòu)長(zhǎng)這樣dormitory-system/ ├── backend/ # SpringBoot后端工程 │ ├── src/main/java/com/dorm/ │ │ ├── controller/ # 接收請(qǐng)求返回JSON │ │ ├── service/ # 業(yè)務(wù)邏輯 │ │ ├── mapper/ # 數(shù)據(jù)訪問層 │ │ ├── entity/ # 實(shí)體類 │ │ ├── config/ # 配置類跨域、攔截器等 │ │ └── common/ # 統(tǒng)一返回結(jié)果、異常處理 │ └── pom.xml ├── frontend/ # Vue前端工程 │ ├── src/ │ │ ├── views/ # 頁(yè)面級(jí)組件如DormitoryManage.vue │ │ ├── components/ # 復(fù)用組件 │ │ ├── router/ # 路由配置 │ │ ├── api/ # 封裝請(qǐng)求 │ │ └── store/ # 全局狀態(tài)管理 │ └── package.json └── sql/ # 數(shù)據(jù)庫(kù)腳本.sql分這么清楚有個(gè)實(shí)打?qū)嵉暮锰幠憧梢栽谝粋€(gè)端口只開后端用Postman調(diào)接口也可以只開前端用Mock數(shù)據(jù)調(diào)試樣式。調(diào)試效率比單體應(yīng)用高很多出問題時(shí)也能快速定位是接口的問題還是頁(yè)面的問題。2.2 技術(shù)選型背后的真實(shí)理由很多人選型時(shí)看哪個(gè)流行選哪個(gè)我建議看哪個(gè)對(duì)當(dāng)前項(xiàng)目收益最高。給課設(shè)做選型時(shí)我考慮過三個(gè)問題第一為什么后端用SpringBoot而不是SSMSSM五年前是主流但配置一堆XML光Spring和MyBatis整合就夠新手喝一壺。SpringBoot把自動(dòng)配置內(nèi)化你只要引入依賴、寫幾個(gè)注解就能跑起來。而且市面上絕大多數(shù)課設(shè)代碼、博客、視頻教程都基于SpringBoot遇到問題搜得到答案這一點(diǎn)在趕工期時(shí)能救命。第二為什么ORM層選MyBatis-Plus這里說句實(shí)在話學(xué)生宿舍管理系統(tǒng)的數(shù)據(jù)查詢復(fù)雜度不高大部分是單表操作加簡(jiǎn)單條件查詢。MyBatis-Plus提供了一整套單表CRUD方法連SQL都不用寫內(nèi)置分頁(yè)插件也很方便。相比原生MyBatis要手動(dòng)維護(hù)XML效率高出不止一點(diǎn)。但它不是萬(wàn)能藥后面講多表聯(lián)查時(shí)你會(huì)看到什么時(shí)候該放棄它、直接手寫SQL。第三為什么前端選Vue而不是React對(duì)做課設(shè)的同學(xué)來說Vue的中文資料和Element UI/Element Plus這類現(xiàn)成組件庫(kù)是核心優(yōu)勢(shì)。你不需要自己手寫一個(gè)好看的后臺(tái)管理界面直接拿組件庫(kù)拼頁(yè)面一天的活兒能縮到兩小時(shí)。這不是投機(jī)取巧而是工程上正常的復(fù)用思維。2.3 版本選擇SpringBoot、JDK、Vue三者搭配是最大的坑我見過太多人死在這上面所以單獨(dú)拉一節(jié)說。搜索熱詞里springboot版本太高能上熱搜真不是沒道理?,F(xiàn)在常見的搭配有兩套項(xiàng)目保守方案推薦課設(shè)用較新方案JDK1.817SpringBoot2.7.x3.xMyBatis-Plus3.5.x3.5.x注意兼容Vue2.6 Vue CLI3.x ViteUI庫(kù)Element UIElement Plus兩套方案都能做出完整項(xiàng)目但如果你用新教程配合老代碼或者反過來多半會(huì)撞上javax和jakarta的報(bào)錯(cuò)。SpringBoot 3.x把javax.servlet改成了jakarta.servlet很多老代碼的import javax.*直接失效。所以我的建議是項(xiàng)目開始之前先定死版本清單寫進(jìn)文檔里。這一步能幫你省掉后面至少兩天的排錯(cuò)時(shí)間。3. 數(shù)據(jù)庫(kù)是整套系統(tǒng)的地基表結(jié)構(gòu)與初始化數(shù)據(jù)怎么設(shè)計(jì)說句可能得罪人的話我看了不少課設(shè)源碼很多能跑的系統(tǒng)數(shù)據(jù)庫(kù)表設(shè)計(jì)是站不住腳的。要么把所有信息塞進(jìn)一張大寬表要么外鍵關(guān)系混亂要么字符集不是utf8mb4導(dǎo)致中文亂碼。數(shù)據(jù)庫(kù)設(shè)計(jì)得不好后面每個(gè)功能寫起來都別扭。3.1 核心表的關(guān)系網(wǎng)用戶、學(xué)生、宿舍、樓棟先理清核心實(shí)體。以我常用的方案為例最終表控制在10張以內(nèi)但關(guān)系清晰sys_user賬號(hào)表存登錄名、密碼BCrypt加密、角色admin/manager/student和學(xué)生表是一對(duì)一或一對(duì)零。t_student學(xué)生表存學(xué)號(hào)、姓名、性別、學(xué)院、班級(jí)、手機(jī)號(hào)、當(dāng)前宿舍ID其中學(xué)號(hào)是天然的業(yè)務(wù)主鍵。t_building樓棟表存樓棟名稱、可容納人數(shù)等。t_dormitory宿舍表存樓棟ID、房間號(hào)、樓層、床位數(shù)、當(dāng)前已住人數(shù)。t_bed床位表把床位單獨(dú)拆一張表。宿舍和床位是一對(duì)多每個(gè)床位有獨(dú)立的狀態(tài)字段。這樣做的好處是分配時(shí)可以精確到床位而不是只能整個(gè)宿舍一起分配也為后續(xù)調(diào)宿、退宿留出了清晰的狀態(tài)流轉(zhuǎn)空間。至于業(yè)務(wù)表常見的有t_repair報(bào)修、t_hygiene衛(wèi)生檢查、t_leave請(qǐng)假或晚歸登記、t_transfer調(diào)宿申請(qǐng)。它們都有共同點(diǎn)一個(gè)業(yè)務(wù)主鍵、一個(gè)關(guān)聯(lián)的外鍵字段、一個(gè)狀態(tài)字段、一條時(shí)間線。這里我特別想強(qiáng)調(diào)一點(diǎn)外鍵到底加不加。課設(shè)里我建議不加數(shù)據(jù)庫(kù)外鍵約束而是把關(guān)聯(lián)關(guān)系放在代碼層維護(hù)。原因有二第一MyBatis-Plus這種框架對(duì)數(shù)據(jù)庫(kù)外鍵沒有特殊支持真正維護(hù)關(guān)系的是業(yè)務(wù)代碼第二有外鍵約束后做刪除和批量初始化數(shù)據(jù)時(shí)會(huì)遇到一堆順序依賴的麻煩。但不加外鍵不代表不設(shè)計(jì)關(guān)系關(guān)系在表和字段層面就已經(jīng)定了外鍵約束只是物理層的保護(hù)。3.2 一份能從頭執(zhí)行到底的SQL建庫(kù)、建表、灌數(shù)據(jù)源碼數(shù)據(jù)庫(kù)文檔三件套里數(shù)據(jù)庫(kù)往往是最容易被忽略、最后又最影響驗(yàn)收的一環(huán)。我給你一個(gè)建議交付的SQL腳本必須是從頭到尾能完整執(zhí)行的包含建庫(kù)、建表、插入初始化數(shù)據(jù)三個(gè)部分。很多同學(xué)導(dǎo)出數(shù)據(jù)庫(kù)時(shí)只導(dǎo)出了表結(jié)構(gòu)和業(yè)務(wù)數(shù)據(jù)評(píng)審老師拿到手根本起不來。我的SQL腳本按這個(gè)順序組織先建庫(kù)CREATE DATABASE dormitory DEFAULT CHARACTER SET utf8mb4;。注意字符集指定utf8mb4光寫utf8在MySQL 5.7之后依然可能出問題。按依賴順序建表sys_user→t_building→t_dormitory→t_bed→t_student→ 各業(yè)務(wù)表。插入初始化數(shù)據(jù)至少包含一個(gè)admin賬號(hào)、一個(gè)宿管賬號(hào)、兩三個(gè)學(xué)生賬號(hào)以及幾條樓棟和床位數(shù)據(jù)。這里有個(gè)經(jīng)驗(yàn)初始化數(shù)據(jù)的密碼記得統(tǒng)一比如都是123456并且用同一種加密算法生成方便演示時(shí)登錄。不要在文檔里寫密碼請(qǐng)自行查看這種話那等于給驗(yàn)收環(huán)節(jié)添堵。3.3 讓統(tǒng)計(jì)報(bào)表不那么難寫的兩個(gè)小技巧宿舍系統(tǒng)很難避開統(tǒng)計(jì)功能入住率、各樓棟人數(shù)、報(bào)修完成率。如果每次統(tǒng)計(jì)都要在代碼里寫一大段循環(huán)去查數(shù)據(jù)庫(kù)既慢又丑。我常用的做法是兩個(gè)層面配合一是增加冗余字段。在t_dormitory表里放一個(gè)已住人數(shù)字段每次分配或退宿時(shí)在同一個(gè)事務(wù)里同步更新床位狀態(tài)和宿舍已住人數(shù)。查詢匯總時(shí)直接對(duì)已住人數(shù)求和不需要實(shí)時(shí)count床位表。你可能會(huì)問冗余字段不怕數(shù)據(jù)不一致嗎怕所以在同一個(gè)事務(wù)內(nèi)更新t_bed和t_dormitory一致性就有保證。二是復(fù)雜統(tǒng)計(jì)直接用SQL的GROUP BY加聚合函數(shù)不要在Java代碼里算。比如按樓棟統(tǒng)計(jì)人數(shù)一行SQL就能解決SELECT b.id, b.name, COUNT(s.id) AS stu_count FROM t_building b LEFT JOIN t_student s ON b.id s.building_id LEFT JOIN sys_user u ON s.student_no u.username WHERE u.role student AND s.status 1 GROUP BY b.id, b.name;這種SQL寫完放進(jìn)Mapper的Select注解里比在Service層寫循環(huán)高效得多答辯時(shí)也更講得清楚。4. 從學(xué)生端到管理端權(quán)限與核心業(yè)務(wù)模塊的實(shí)現(xiàn)邏輯骨架和數(shù)據(jù)庫(kù)搭好之后該解決系統(tǒng)怎么運(yùn)轉(zhuǎn)的問題了。這一章講三個(gè)核心實(shí)現(xiàn)邏輯分別對(duì)應(yīng)三個(gè)最容易答辯翻車的點(diǎn)登錄鑒權(quán)、宿舍分配、狀態(tài)類業(yè)務(wù)流轉(zhuǎn)。4.1 登錄鑒權(quán)前后端分離下我是誰(shuí)的問題傳統(tǒng)單體應(yīng)用可以用Session前后端分離后我更推薦用JWT做無狀態(tài)鑒權(quán)。流程很簡(jiǎn)單用戶輸入賬號(hào)密碼后端校驗(yàn)通過后生成一個(gè)JWT字符串里面帶上用戶ID和角色通過接口返回給前端。前端把token存起來之后每次請(qǐng)求都在Header里帶上Authorization: Bearer token。后端寫一個(gè)攔截器統(tǒng)一攔截除登錄接口之外的請(qǐng)求解析并校驗(yàn)token通過后放行不通過返回401。注意幾個(gè)細(xì)節(jié)。密碼不要明文存儲(chǔ)用BCrypt或MD5加鹽。課設(shè)用BCrypt更顯專業(yè)Spring Security里自帶BCryptPasswordEncoder但不想引入完整Security框架的話也可以單獨(dú)引入Spring Security Crypto的依賴只拿它的加密工具類。token有效期建議設(shè)24小時(shí)引入Redis做黑名單會(huì)更專業(yè)但對(duì)課設(shè)場(chǎng)景來說屬于超綱也容易把自己繞暈可以不引入。攔截器的實(shí)現(xiàn)參考這樣Component public class JwtInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); // 校驗(yàn)token合法則把用戶信息放入request上下文 // 不合法則返回401并終止請(qǐng)求 return true; } }記得在配置類里注冊(cè)攔截器并且放行/api/login和靜態(tài)資源路徑。這個(gè)配置遺忘率非常高很多人部署后頁(yè)面打不開就是因?yàn)殪o態(tài)資源被攔截器攔了。4.2 宿舍分配床位狀態(tài)機(jī)和并發(fā)問題宿舍分配是整個(gè)系統(tǒng)里業(yè)務(wù)邏輯最像樣的部分也是答辯老師最喜歡深挖的地方。一個(gè)學(xué)生申請(qǐng)入住時(shí)怎么保證他拿到的床位真的是空的如果兩個(gè)管理員同時(shí)操作會(huì)不會(huì)把同一個(gè)床位分給兩個(gè)人我的方案是給床位加狀態(tài)字段并在分配事務(wù)里做條件更新。床位的狀態(tài)機(jī)是0-空閑可以被分配1-已入住不可分配2-維修中不可分配分配的核心邏輯是先根據(jù)宿舍ID查可用的空閑床位然后用帶狀態(tài)條件的SQL去更新boolean success bedMapper.updateByCondition( // 設(shè)置新狀態(tài) new Bed().setStatus(1).setStudentId(studentId), // 條件為床位ID匹配且當(dāng)前狀態(tài)為0 new LambdaQueryWrapperBed() .eq(Bed::getId, bedId) .eq(Bed::getStatus, 0) ) 0;關(guān)鍵在于WHERE id? AND status0。如果返回更新行數(shù)為0說明床位已經(jīng)被別人搶走了本次分配失敗重新選擇床位即可。這其實(shí)就是樂觀鎖的思路不需要引入分布式鎖用數(shù)據(jù)庫(kù)自帶的行鎖就能解決。調(diào)宿和退宿都是在這個(gè)狀態(tài)機(jī)上做流轉(zhuǎn)。退宿把床位狀態(tài)還原為空閑同時(shí)清空學(xué)生ID關(guān)聯(lián)。把關(guān)鍵約束放在數(shù)據(jù)庫(kù)字段和更新條件里比在Java代碼里寫一堆if-else要穩(wěn)得多。4.3 報(bào)修、衛(wèi)生檢查這類狀態(tài)流轉(zhuǎn)業(yè)務(wù)怎么做學(xué)生報(bào)修→宿管查看→維修處理→學(xué)生確認(rèn)這類流程本質(zhì)上就是一張表加上一個(gè)狀態(tài)字段的流轉(zhuǎn)區(qū)別只在于哪個(gè)角色能改狀態(tài)。實(shí)現(xiàn)時(shí)我建議統(tǒng)一返回格式{ code: 200, message: 操作成功, data: {} }前端用Axios統(tǒng)一攔截解析code并做提示后端用RestControllerAdvice做全局異常處理。這樣一來報(bào)修模塊、衛(wèi)生模塊、請(qǐng)假模塊都可以復(fù)用同一套結(jié)構(gòu)和邏輯代碼量能壓縮不少。表單提交前前端做一次必填校驗(yàn)和手機(jī)號(hào)格式校驗(yàn)后端接口再做一次非空和長(zhǎng)度校驗(yàn)雙保險(xiǎn)。千萬(wàn)別只做前端校驗(yàn)因?yàn)榻涌谑强梢员恢苯诱{(diào)用的。這是一個(gè)非?;A(chǔ)但常見的扣分點(diǎn)。5. 把前端打包塞進(jìn)SpringBoot從本地聯(lián)調(diào)到服務(wù)器部署代碼寫完了最折騰人的其實(shí)是怎么讓前后端真正跑在一起。我見過太多項(xiàng)目在本地跑得好好的一到部署就崩。這一章把聯(lián)調(diào)、跨域、部署三個(gè)環(huán)節(jié)說透。5.1 跨域問題前端端口和后端端口八字不合的根源開發(fā)環(huán)境下前端跑在localhost:8080后端跑在localhost:9090端口不同瀏覽器的同源策略就會(huì)攔下請(qǐng)求這就是跨域。解決辦法有兩種第一種后端直接加CORS配置類允許前端地址訪問。寫一個(gè)WebMvcConfigurer配置類重寫addCorsMappings方法允許所有來源和所有請(qǐng)求方法即可。這種方式簡(jiǎn)單直觀適合課設(shè)。第二種前端用Vite或Vue CLI的代理功能把/api開頭的請(qǐng)求代理到后端地址。開發(fā)期用代理更接近生產(chǎn)環(huán)境改接口地址時(shí)不用動(dòng)前端代碼。這兩種方式我都試過開發(fā)期推薦代理生產(chǎn)期推薦直接打包進(jìn)后端同源部署整個(gè)系統(tǒng)只有一個(gè)地址沒有跨域問題。5.2 兩種打包部署方式先看懂再選擇第一種是Vue打包放進(jìn)SpringBoot。在frontend目錄執(zhí)行npm run build得到dist目錄把里面的靜態(tài)文件復(fù)制到后端src/main/resources/static下然后重新打包后端的jar。這樣整個(gè)系統(tǒng)只有一個(gè)jar包里面既包含后端接口也包含前端頁(yè)面。部署時(shí)用java -jar dormitory.jar就能跑非常省事。對(duì)應(yīng)的前端請(qǐng)求接口的地址不要寫死成http://localhost:9090/api應(yīng)該用相對(duì)路徑/api這樣在同一個(gè)Tomcat下才不出問題。第二種是前后端分離部署。后端jar包跑在9090端口前端dist目錄交給Nginx托管Nginx配置反向代理把/api請(qǐng)求轉(zhuǎn)發(fā)給9090的SpringBoot進(jìn)程。這種部署方式更貼近真實(shí)企業(yè)環(huán)境適合在文檔里寫未來可擴(kuò)展性也方便把靜態(tài)資源獨(dú)立管理。但如果你在校期間沒有云服務(wù)器用第一種方式就足夠了。這里直接給出一份Nginx靜態(tài)托管加反向代理的關(guān)鍵配置server { listen 80; server_name your_domain_or_ip; root /usr/share/nginx/html/dist; index index.html; location /api/ { proxy_pass http://127.0.0.1:9090; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }5.3 部署時(shí)的常見問題端口、數(shù)據(jù)庫(kù)連接、配置文件部署踩坑主要集中在三件事端口被占用Linux服務(wù)器上用netstat -tlnp查端口找到占用8080或9090的進(jìn)程處理掉。Windows下對(duì)應(yīng)的是netstat -ano加任務(wù)管理器但服務(wù)器大概率是Linux。數(shù)據(jù)庫(kù)連接不上大概率是數(shù)據(jù)庫(kù)地址寫成了localhost而客戶端和數(shù)據(jù)庫(kù)不在同一臺(tái)機(jī)器。把a(bǔ)pplication.yml里的url改成服務(wù)器的IP或內(nèi)網(wǎng)地址并確認(rèn)3306端口在防火墻或安全組里放行。配置文件分環(huán)境我的習(xí)慣是application-dev.yml和application-prod.yml兩套配置啟動(dòng)時(shí)用--spring.profiles.activeprod指定。課設(shè)雖然不強(qiáng)制但這個(gè)習(xí)慣寫在文檔里評(píng)委印象分會(huì)高不少。6. 配套文檔怎么寫答辯才不至于一問三不知標(biāo)題里的三件套源碼和數(shù)據(jù)庫(kù)都聊完了最后說文檔。我見過不少學(xué)生代碼寫得不錯(cuò)文檔卻很糟糕答辯時(shí)只能干巴巴地說我用了SpringBoot和Vue。文檔其實(shí)是給評(píng)委的第一印象在答辯中占的比重有時(shí)候比代碼本身還高。6.1 課設(shè)文檔的黃金結(jié)構(gòu)從需求到驗(yàn)證一脈相承不要從網(wǎng)上下一個(gè)萬(wàn)能模板套上去而是圍繞邏輯主線自證合理性。我的建議順序是需求分析把系統(tǒng)用戶和用例列清楚。學(xué)生能干什么、宿管能干什么、管理員能干什么。這是整份文檔的根基。系統(tǒng)設(shè)計(jì)畫整體架構(gòu)圖前后端分離、標(biāo)注技術(shù)棧再加數(shù)據(jù)庫(kù)ER圖和表結(jié)構(gòu)說明。表結(jié)構(gòu)說明要包含字段名、類型、是否主鍵、含義。評(píng)委不一定逐行看代碼但會(huì)掃一眼表設(shè)計(jì)是否合理字段命名是否規(guī)范。核心模塊設(shè)計(jì)選兩三個(gè)最能體現(xiàn)技術(shù)能力的模塊深入寫比如宿舍分配的并發(fā)控制、JWT鑒權(quán)流程。這里是你得分的地方一定要把為什么這么設(shè)計(jì)寫出來。系統(tǒng)實(shí)現(xiàn)與測(cè)試貼關(guān)鍵界面截圖和接口測(cè)試結(jié)果順帶寫一個(gè)簡(jiǎn)單的測(cè)試用例表比如測(cè)試正常分配、測(cè)試重復(fù)分配、測(cè)試權(quán)限攔截??偨Y(jié)與展望一兩句話帶過即可重點(diǎn)是實(shí)現(xiàn)了什么、還能優(yōu)化什么。不要寫我相信該系統(tǒng)具有良好的應(yīng)用前景這種空話改成后續(xù)可引入消息隊(duì)列處理報(bào)修通知這種具體方向。6.2 答辯演示的節(jié)奏核心鏈路優(yōu)先別從登錄頁(yè)開始講20分鐘答辯演示是很多同學(xué)忽略的環(huán)節(jié)。我的經(jīng)驗(yàn)是按核心鏈路演示不要按菜單順序演示。菜單順序演示的問題在于講者容易陷入一個(gè)個(gè)頁(yè)面的截圖流評(píng)委聽不出業(yè)務(wù)閉環(huán)。核心鏈路演示則不一樣第一步用管理員賬號(hào)登錄展示學(xué)生信息和樓棟宿舍列表說明數(shù)據(jù)如何錄入。 第二步走一遍學(xué)生入住分配床位的完整流程順便展示床位狀態(tài)的實(shí)時(shí)變化。這里是體現(xiàn)數(shù)據(jù)庫(kù)設(shè)計(jì)和業(yè)務(wù)邏輯的最好時(shí)機(jī)。 第三步用學(xué)生賬號(hào)登錄演示提交一條報(bào)修再切回宿管賬號(hào)處理這條報(bào)修只講狀態(tài)流轉(zhuǎn)。 第四步打開統(tǒng)計(jì)頁(yè)面展示入住率和報(bào)修處理率解釋這兩組數(shù)據(jù)是怎么算出來的。整個(gè)演示控制在5到8分鐘評(píng)委對(duì)系統(tǒng)業(yè)務(wù)閉環(huán)的感知會(huì)非常清晰。接著你再講設(shè)計(jì)亮點(diǎn)JWT、樂觀鎖、統(tǒng)一異常處理基本就是順著你的節(jié)奏走了。6.3 三件套交付前最后花半小時(shí)自查一遍交付前的自查清單我整理一份直接可用的SQL腳本能不能從空數(shù)據(jù)庫(kù)直接完整執(zhí)行不報(bào)錯(cuò)初始賬號(hào)是否能正常登錄角色是否正確前端打包后的靜態(tài)文件是否已經(jīng)放進(jìn)了SpringBoot的static目錄能不能在只裝JDK和MySQL的環(huán)境下用一條java -jar命令把系統(tǒng)跑起來文檔里的截圖是不是最新界面的截圖有沒有殘留舊版頁(yè)面外鍵、時(shí)區(qū)、字符集、跨域這些配置是否在文檔中有說明這半小時(shí)的檢查能幫你避免很多老師當(dāng)場(chǎng)打開卻發(fā)現(xiàn)跑不起來的尷尬場(chǎng)景。我做課設(shè)和幫朋友驗(yàn)收項(xiàng)目時(shí)每次都跑一遍這個(gè)流程。最后再說一個(gè)小習(xí)慣在SQL腳本和接口路徑的命名上盡量保持規(guī)整和語(yǔ)義化接口統(tǒng)一用/api前綴表名統(tǒng)一用t_開頭。你說不上這是哪個(gè)大功能但評(píng)委翻代碼時(shí)視覺上的規(guī)整會(huì)潛移默化地影響他對(duì)你代碼質(zhì)量的判斷。這些細(xì)節(jié)積累起來就是同一套功能有人被夸工程化意識(shí)強(qiáng)有人被批這是玩具項(xiàng)目的根本區(qū)別。