系統(tǒng)畢業(yè)設(shè)計(jì):環(huán)境配置到答辯全攻略)
簡(jiǎn)介基于Java、SSM框架SpringSpringMVCMyBatis、MySQL數(shù)據(jù)庫及微信小程序的家政服務(wù)管理系統(tǒng)畢業(yè)設(shè)計(jì)資源面向計(jì)算機(jī)專業(yè)畢業(yè)生及需要課程設(shè)計(jì)、期末項(xiàng)目的學(xué)生。項(xiàng)目包含完整前后端源碼、數(shù)據(jù)庫腳本和畢業(yè)論文開發(fā)環(huán)境為Idea、微信開發(fā)者工具并配套Maven部署與Navicat數(shù)據(jù)庫管理已通過嚴(yán)格調(diào)試可直接運(yùn)行使用。資源包共1213個(gè)文件大小16.41MB以png圖片、js腳本、svg圖標(biāo)、vue頁面、java類、json配置、wxss樣式及wxml小程序結(jié)構(gòu)文件為主另有少量sql數(shù)據(jù)庫腳本和docx論文文檔目錄結(jié)構(gòu)完整清晰。目前已有85人學(xué)習(xí)下載。系統(tǒng)實(shí)現(xiàn)了用戶端與服務(wù)端的分離覆蓋家政服務(wù)發(fā)布、訂單管理、評(píng)價(jià)反饋等核心功能界面簡(jiǎn)潔美觀操作便捷。隨附的論文詳細(xì)闡述了需求分析、數(shù)據(jù)庫設(shè)計(jì)與系統(tǒng)實(shí)現(xiàn)過程既可作為畢業(yè)設(shè)計(jì)寫作范本也可作為二次開發(fā)的基礎(chǔ)框架。1. 家政小程序憑什么能當(dāng)高分畢業(yè)設(shè)計(jì)先把這套 SSM 加微信小程序組合拆開看家政服務(wù)小程序這個(gè)題目在計(jì)算機(jī)畢業(yè)設(shè)計(jì)里屬于經(jīng)典款中的穩(wěn)重款后端是 Java 語言SSMSpring、SpringMVC、MyBatis框架數(shù)據(jù)庫用 MySQL前端用一個(gè)微信小程序承載。它模擬的是真實(shí)到家服務(wù)平臺(tái)的骨架——用戶打開小程序?yàn)g覽保潔、月嫂、家電維修這些服務(wù)選中后填寫地址和期望時(shí)間下單服務(wù)人員接單、完成服務(wù)后雙方還能評(píng)價(jià)。相比電商、外賣這些被寫過無數(shù)次的選題家政的業(yè)務(wù)鏈條更短但狀態(tài)流轉(zhuǎn)完整正好卡在畢業(yè)設(shè)計(jì)要完整不要復(fù)雜的甜點(diǎn)上。那這個(gè)項(xiàng)目解決的是誰的什么問題如果你是 Java 方向的學(xué)生手里已經(jīng)學(xué)過 SSM 和 MySQL 教材但從來沒把瀏覽器、小程序、后端、數(shù)據(jù)庫四層串通過這套源碼就是最好的練手素材。如果你是準(zhǔn)備求職面試需要一個(gè)能當(dāng)場(chǎng)演示、講得出設(shè)計(jì)細(xì)節(jié)的項(xiàng)目家政小程序也比圖書管理、學(xué)生管理這類 CRUD 項(xiàng)目更有記憶點(diǎn)。后面我不講虛的直接按拿到源碼后從環(huán)境配置到答辯演示的完整路徑展開。2. 把 SSM 后端在本地跑起來環(huán)境版本到接口驗(yàn)證的一整套配置先潑一盆冷水拿到源碼數(shù)據(jù)庫論文的壓縮包最耗時(shí)間的環(huán)節(jié)通常不是寫代碼而是把項(xiàng)目跑起來。SSM 是 2015 年那會(huì)兒的主流 Java Web 技術(shù)棧現(xiàn)在電腦上裝的往往是新版 JDK、新版 Tomcat、新版 MySQL版本不匹配時(shí)光啟動(dòng)報(bào)錯(cuò)就能耗掉一個(gè)周末。這章我把從解壓到接口驗(yàn)證的完整步驟寫出來每一步都標(biāo)明版本和參數(shù)。2.1 環(huán)境選型JDK 8、Maven 3.6、Tomcat 8.5 的兼容性說明這個(gè)項(xiàng)目能跑起來的前提是環(huán)境的兼容性。我一般固定用JDK 1.8、Maven 3.6.x、Tomcat 8.5 或 9.0、MySQL 5.78.0 也可以但連接參數(shù)要改。不要嘗試用 JDK 17 或 Tomcat 10翻車概率極高。為什么因?yàn)槔享?xiàng)目的 pom.xml 依賴的是 javax.servlet 命名空間Tomcat 10 開始把包名改成了 jakarta.servlet一啟動(dòng)就 NoClassDefFoundError。JDK 17 對(duì) Spring 5.2.x 的反射訪問也有限制處理起來很鬧心。這里沒有捷徑照著老版本配項(xiàng)目起來得最快。組件推薦版本替代版本注意JDK1.81117 需改 Spring 依賴Tomcat8.59.010 起是 jakarta 命名空間MySQL5.78.08.0 連接串要加時(shí)區(qū)Maven3.6.x3.8.x配阿里云鏡像更穩(wěn)Maven 的 settings.xml 里建議配上阿里云鏡像。中國大陸網(wǎng)絡(luò)訪問 Maven 中央倉庫經(jīng)常超時(shí)第一次拉 SSM 全家桶依賴會(huì)很大不配鏡像的話下載可能卡在某個(gè) jar 上半小時(shí)。2.2 導(dǎo)入 IDEA 與首次構(gòu)建Maven 鏡像和編譯檢查解壓源碼包后先看目錄頂層有沒有 pom.xml。IDEA 打開時(shí)直接選擇 pom.xml 所在的目錄IDEA 會(huì)識(shí)別為 Maven 項(xiàng)目。導(dǎo)入后打開右側(cè) Maven 面板先執(zhí)行 clean 再執(zhí)行 compilemvn clean compile如果依賴下載卡住去改 Maven 全局配置文件 conf/settings.xmlmirror idaliyunmaven/id mirrorOfcentral/mirrorOf namealiyun maven public/name urlhttps://maven.aliyun.com/repository/public/url /mirror參數(shù)說明mirrorOf寫中央倉庫的 idurl指向阿里云的公共倉庫。這一步是標(biāo)準(zhǔn)的 Maven 配置不單是 SSM 用得到以后所有 Java 項(xiàng)目都受益。編譯通過后檢查 src/main/webapp/WEB-INF 下有沒有 web.xml。SSM 項(xiàng)目的請(qǐng)求分發(fā)全靠 DispatcherServlet 在 web.xml 里注冊(cè)沒有這個(gè)文件Tomcat 啟動(dòng)不會(huì)報(bào)錯(cuò)但所有接口都是 404。2.3 修改數(shù)據(jù)庫連接jdbc.properties 里的三個(gè)必改參數(shù)SSM 的數(shù)據(jù)庫配置通常收斂在一個(gè) properties 文件里常見路徑是 src/main/resources/jdbc.properties 或 db.properties。修改的地方有三個(gè)數(shù)據(jù)庫地址、用戶名、密碼。# 家政項(xiàng)目的 MySQL 連接配置 jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/household?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse jdbc.usernameroot jdbc.password123456逐個(gè)說參數(shù)useUnicodetruecharacterEncodingutf8是讓 MySQL 連接按 UTF-8 字符集傳輸數(shù)據(jù)不配這個(gè)后面中文亂碼問題會(huì)直接噴到小程序頁面上serverTimezoneAsia/Shanghai是給 MySQL 8.0 用的不加可能報(bào)時(shí)區(qū)錯(cuò)誤useSSLfalse是關(guān)閉 MySQL 8.0 默認(rèn)的 SSL 握手。密碼如果是空也要寫空字符串否則 DBCP 連接池會(huì)用默認(rèn)值去連直接 Access denied。改完之后檢查 Spring 的配置文件通常是 applicationContext.xml 或 spring-mybatis.xml里有沒有引用這個(gè) properties 文件。常見錯(cuò)誤是路徑寫錯(cuò)或文件名打錯(cuò)導(dǎo)致${jdbc.url}占位符解析失敗。文件名的拼寫錯(cuò)誤很難發(fā)現(xiàn)建議直接復(fù)制。2.4 初始化 MySQL 數(shù)據(jù)庫建庫、建表、數(shù)據(jù)字典對(duì)齊源碼包里一般帶 sql 腳本。我建議把腳本內(nèi)容從頭到尾看一遍不要無腦執(zhí)行原因后面說。執(zhí)行方式有兩種命令行或者 Navicat。命令行建庫和導(dǎo)表分開做可讀性最好CREATE DATABASE IF NOT EXISTS household DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE household; SOURCE /absolute/path/household.sql;注意SOURCE后面要寫絕對(duì)路徑。如果你的 sql 腳本第一行已經(jīng)有 CREATE DATABASE跳過建庫這一步直接mysql -u root -p household.sql也行。腳本執(zhí)行完后SHOW TABLES;確認(rèn)表的數(shù)量。常見家政項(xiàng)目的核心表至少包含用戶表sys_user 或 t_user、服務(wù)分類表t_category、訂單表t_order、評(píng)價(jià)表t_comment。如果你看到表很少先不要慌可能是題目本身功能精簡(jiǎn)但如果論文里的數(shù)據(jù)字典有 15 張表而數(shù)據(jù)庫只有 3 張那是腳本版本不對(duì)需要找完整版腳本別自己硬補(bǔ)表。這一步最容易翻車的點(diǎn)是執(zhí)行后中文亂碼。檢查方法是用 SELECT 查一條帶中文的記錄在命令行里顯示正常再去小程序里看。命令行顯示亂碼而數(shù)據(jù)庫存儲(chǔ)正常那只是客戶端字符集問題不影響使用如果數(shù)據(jù)庫本身就存的是亂碼就要回到建庫語句的 DEFAULT CHARACTER SET 檢查。2.5 啟動(dòng) Tomcat 并驗(yàn)證接口瀏覽器和 curl 雙確認(rèn)數(shù)據(jù)庫就緒后配置啟動(dòng)。IDEA 右上角點(diǎn) Add Configuration選 Tomcat Server - LocalDeployment 里選擇 war exploded 模式Application context 填/household。確認(rèn) Tomcat 端口默認(rèn) 8080沒被占用后點(diǎn) Debug 啟動(dòng)。啟動(dòng)日志出現(xiàn)這兩行說明 Spring 容器初始化完成Root WebApplicationContext: initialization completed Tomcat started on port(s): 8080然后先用瀏覽器訪問http://localhost:8080/household/只要能彈出頁面或 JSON說明 web 應(yīng)用已掛載。再用 curl 打一個(gè)真實(shí)的查詢接口curl http://localhost:8080/household/api/service/list返回 JSON 數(shù)組說明 DispatcherServlet 和 MyBatis 查詢鏈路都通。如果 404檢查 controller 的 RequestMapping 和 web.xml 的 servlet-mapping url-pattern常見是/或/api/*如果 500看 IDEA 日志最底部的 Caused by是 SQL 語法錯(cuò)了還是連接失敗了。后端跑通后接下來是小程序端的接入。3. 微信小程序端從 0 到真機(jī)預(yù)覽baseUrl、登錄態(tài)與調(diào)試開關(guān)后端跑通只是第一步家政項(xiàng)目的主戰(zhàn)場(chǎng)在小程序端。微信開發(fā)者工具的版本、appid 是否有效、請(qǐng)求地址指向哪里這三個(gè)問題不開好頭后面全是黑匣子報(bào)錯(cuò)。這一章把小程序端從打開到真機(jī)預(yù)覽的配置鏈路完整走一遍。3.1 小程序目錄結(jié)構(gòu)pages、utils、app.js 各管什么拿到源碼后小程序部分通常是一個(gè)獨(dú)立的文件夾比如 miniprogram 或 house-app。先打開 project.config.json 看 appid{ appid: wx1234567890abcdef, compileType: miniprogram, projectname: household-app }如果沒有自己的小程序賬號(hào)去微信公眾平臺(tái)注冊(cè)一個(gè)個(gè)人主體小程序或者用測(cè)試號(hào)。appid 和你后端調(diào)用 code2session 時(shí)要用的 appid 必須是同一個(gè)不然后端生成的登錄態(tài)永遠(yuǎn)對(duì)不上。目錄結(jié)構(gòu)上pages 下面每個(gè)業(yè)務(wù)頁面一個(gè)文件夾里面是四個(gè)同名的文件wxml結(jié)構(gòu)、wxss樣式、js邏輯、json頁面配置。utils 里通常放著 request.js 這種通用模塊。app.js 是全局入口App({...}) 里 onLaunch 做初始化。家政項(xiàng)目一般有首頁服務(wù)列表、下單頁、訂單列表頁、個(gè)人中心頁這幾個(gè)頁面先在 app.json 里確認(rèn)頁面注冊(cè)路徑?jīng)]有寫錯(cuò)否則編譯不報(bào)錯(cuò)但頁面白屏。3.2 修改 baseUrl為什么 localhost 不行局域網(wǎng) IP 才行這是小白最容易卡住的一個(gè)點(diǎn)。requests 的地址寫在 utils/config.js 里默認(rèn)可能是http://localhost:8080。在開發(fā)者工具里模擬器環(huán)境里訪問 localhost 指向的不是你的 Windows 或 Mac而是模擬器自己所以請(qǐng)求必然失敗。改成你電腦在局域網(wǎng)里的 IP 地址在終端里用 ipconfigWindows或 ifconfigMac查// utils/config.js module.exports { baseUrl: http://192.168.1.100:8080/household, // 指向本機(jī)后端 timeout: 10000 }注意 baseUrl 末尾要不要帶項(xiàng)目上下文路徑取決于后端 Tomcat 的 Application context 配置。如果 context 是/household那這里就要帶上如果 context 是/這里就是http://192.168.1.100:8080。注意換 IP 后記得同步檢查后端 Tomcat 的 context path前綴不一致是最隱蔽的聯(lián)調(diào)翻車點(diǎn)。3.3 微信登錄的完整閉環(huán)wx.login 到 code2session家政小程序的登錄方式是微信一鍵登錄這套流程面試和答辯都愛問值得徹底搞明白。前端邏輯是用戶點(diǎn)登錄小程序調(diào) wx.login 拿到臨時(shí)登錄憑證 code這個(gè) code 有效期很短且只能用一次前端把它 POST 給后端后端拿著 code appid secret 去微信的 jscode2session 接口換 openid 和 session_keyopenid 是用戶在本小程序里的唯一 ID后端拿它查表查到就更新昵稱頭像查不到就幫他注冊(cè)一個(gè)新用戶最后后端生成一個(gè)自定義 token 返回給前端前端存到 Storage。后端參考代碼PostMapping(/api/login) ResponseBody public Result login(RequestBody MapString, String params) { String code params.get(code); String url https://api.weixin.qq.com/sns/jscode2session?appid appid secret secret js_code code grant_typeauthorization_code; // 用 HttpClient 發(fā)起 GET 請(qǐng)求解析返回的 openid String openid httpGet(url).getString(openid); User user userMapper.selectByOpenid(openid); if (user null) { user new User(); user.setOpenid(openid); userMapper.insert(user); } String token UUID.randomUUID().toString().replace(-, ); return Result.ok(token); }前端對(duì)應(yīng)wx.login({ success: (res) { if (res.code) { wx.request({ url: getApp().globalData.baseUrl /api/login, method: POST, data: { code: res.code }, success: (res) { wx.setStorageSync(token, res.data.token) } }) } } })要點(diǎn)有兩個(gè)一是 code 只能消費(fèi)一次前端不要在日志里反復(fù)重試二是后端拿到 session_key 后可以不用保存它openid 才是真正要落庫的字段。token 的生成可以簡(jiǎn)單用 UUID但更規(guī)范的做法是放到 Redis這個(gè)項(xiàng)目沒引入 Redis用一張 token 表或把 token 和過期時(shí)間存到內(nèi)存也行答辯時(shí)能自圓其說即可。3.4 真機(jī)預(yù)覽前必須打開的調(diào)試開關(guān)與后臺(tái)域名配置本地開發(fā)時(shí)微信開發(fā)者工具默認(rèn)自帶的校驗(yàn)規(guī)則會(huì)攔掉 HTTP 明文請(qǐng)求和未配置域名具體動(dòng)作是工具右上角詳情 - 本地設(shè)置 - 勾選不校驗(yàn)合法域名、web-view業(yè)務(wù)域名、TLS 版本以及 HTTPS 證書。這個(gè)開關(guān)只管開發(fā)者工具不影響正式發(fā)布。真機(jī)預(yù)覽要再走一步手機(jī)微信打開項(xiàng)目后點(diǎn)擊右上角膠囊按鈕 - 打開調(diào)試。不開這個(gè)手機(jī)端同樣會(huì)攔截 http://192.168.1.100 的請(qǐng)求。這里要說清楚安全和示范的邊界——正式上線必須用備案過的 HTTPS 域名并配置到公眾平臺(tái)后臺(tái)的 request 合法域名列表但畢業(yè)設(shè)計(jì)展示階段局域網(wǎng) IP 直連后端是行業(yè)里最常見的演示做法夠用且高效。小程序端接完整個(gè)聯(lián)調(diào)最核心的兩段就通了。下面看數(shù)據(jù)庫模型為什么長(zhǎng)這樣。4. 家政業(yè)務(wù)的數(shù)據(jù)模型訂單表怎么設(shè)計(jì)才能撐起整個(gè)項(xiàng)目前兩章把項(xiàng)目跑通了但很多照著做的人會(huì)卡在同一個(gè)問題業(yè)務(wù)邏輯看不懂改需求不知道動(dòng)哪張表。這一章把家政項(xiàng)目的數(shù)據(jù)模型按四張核心表 - 狀態(tài)流轉(zhuǎn) - 設(shè)計(jì)理由講透。數(shù)據(jù)庫設(shè)計(jì)是畢業(yè)設(shè)計(jì)論文里最好寫又最容易寫砸的部分因?yàn)樗苯臃从衬阌袥]有真正理解業(yè)務(wù)。4.1 核心表拆解用戶、服務(wù)分類、訂單、評(píng)價(jià)四張表的字段設(shè)計(jì)家政項(xiàng)目的骨相用四張表就能撐住。第一張是用戶表CREATE TABLE sys_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, openid VARCHAR(64) NOT NULL UNIQUE, -- 微信身份標(biāo)識(shí) nickname VARCHAR(64), avatar VARCHAR(255), phone VARCHAR(20), role TINYINT DEFAULT 1 COMMENT 1-用戶 2-服務(wù)人員 3-管理員, create_time DATETIME );openid加唯一約束避免同一微信號(hào)注冊(cè)多個(gè)賬號(hào)。role字段決定了這個(gè)人的操作權(quán)限普通用戶能下單和評(píng)價(jià)服務(wù)人員能接單管理員能管理分類和人員。第二張是服務(wù)分類表CREATE TABLE service_category ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(32) NOT NULL, icon VARCHAR(255), sort_order INT DEFAULT 0, status TINYINT DEFAULT 1, create_time DATETIME );第三張是訂單表這是整個(gè)系統(tǒng)的核心CREATE TABLE t_order ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE, -- 業(yè)務(wù)訂單號(hào) user_id BIGINT NOT NULL, -- 下單人 category_id BIGINT, -- 服務(wù)分類 service_item VARCHAR(255), -- 服務(wù)項(xiàng)目描述 service_time DATETIME, -- 期望服務(wù)時(shí)間 address VARCHAR(255), contact_name VARCHAR(32), contact_phone VARCHAR(20), amount DECIMAL(10,2), status TINYINT DEFAULT 0 COMMENT 0-待接單 1-服務(wù)中 2-已完成 3-已取消, remark VARCHAR(255), create_time DATETIME );第四張是評(píng)價(jià)表CREATE TABLE order_comment ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_id BIGINT NOT NULL UNIQUE, -- 一單只能評(píng)價(jià)一次 user_id BIGINT NOT NULL, rating TINYINT, content VARCHAR(512), images VARCHAR(1000), create_time DATETIME );四張表的關(guān)系一句話能說清一個(gè)用戶下多張訂單一張訂單對(duì)應(yīng)一個(gè)服務(wù)分類服務(wù)完成后產(chǎn)生一條評(píng)價(jià)。設(shè)計(jì)時(shí)注意兩個(gè)容易漏的點(diǎn)一是訂單表不直接存服務(wù)人員的 user_id而是通過接單動(dòng)作在訂單狀態(tài)里附加 service_staff_id 這類字段這樣從待接單到服務(wù)中人員變更有記錄可查二是評(píng)價(jià)表對(duì) order_id 加唯一約束保證一單只能評(píng)價(jià)一次這個(gè)約束放在持久層比在業(yè)務(wù)層判斷可靠得多。4.2 訂單狀態(tài)流轉(zhuǎn)用 status 字段表達(dá)待接單、服務(wù)中、已完成、已取消訂單表里的 status 是整個(gè)家政系統(tǒng)的心跳。我建議用整數(shù)做狀態(tài)值不直接用字符串因?yàn)檫\(yùn)算和比較方便同時(shí)用常量類集中管理public class OrderStatus { public static final int WAIT_ACCEPT 0; // 待接單 public static final int SERVING 1; // 服務(wù)中 public static final int FINISHED 2; // 已完成 public static final int CANCELED 3; // 已取消 }合法的狀態(tài)流轉(zhuǎn)是用戶提交訂單 - 0服務(wù)人員接單 - 1服務(wù)完成確認(rèn) - 2用戶在狀態(tài)為 0 時(shí)取消 - 3。在 Service 層做守衛(wèi)校驗(yàn)已取消的訂單不能再接單已完成的訂單不能再次修改。代碼層面可以在 update 語句里帶上當(dāng)前狀態(tài)條件比如UPDATE t_order SET status 1, service_staff_id #{staffId} WHERE id #{orderId} AND status 0這條 SQL 的巧妙之處在于用AND status 0保證只有待接單訂單能被搶單執(zhí)行完后受影響行數(shù)為 0 說明訂單已被別人接走。這是樂觀鎖思路在狀態(tài)流轉(zhuǎn)里的最小實(shí)現(xiàn)比先查再改安全得多也適合在答辯時(shí)講。狀態(tài)流轉(zhuǎn)圖畫清楚配合這段 SQL老師再追問并發(fā)場(chǎng)景你也有東西可講。4.3 這種數(shù)據(jù)模型為什么能撐起答辯ER 圖、索引與第三范式答辯老師看數(shù)據(jù)庫設(shè)計(jì)第一眼找 ER 圖第二眼找數(shù)據(jù)字典第三眼才問 SQL 細(xì)節(jié)。ER 圖用 Visio 或 draw.io 畫關(guān)系是用戶 1—N 訂單服務(wù)分類 1—N 訂單訂單 1—1 評(píng)價(jià)。不要把用戶和評(píng)價(jià)直接連線雖然從語義上說得通但那樣 ER 圖就多了一條冗余關(guān)系。索引方面訂單表的 user_id 和 status 建普通索引評(píng)價(jià)表的 order_id 建唯一索引。這塊的理由一句話訂單列表頁按用戶查詢、按狀態(tài)篩選是最高頻路徑索引能讓你在演示時(shí)用 WHERE 查詢秒回。當(dāng)然量小看不出差別但索引設(shè)計(jì)意識(shí)本身就是答辯評(píng)分的觀察點(diǎn)。第三范式的話題要會(huì)講。訂單里不冗余存服務(wù)名稱而是存 category_id需要時(shí) JOIN 分類表這個(gè)設(shè)計(jì)的本質(zhì)是消除傳遞依賴。反過來舉一個(gè)反面例子如果訂單表存了分類名稱分類改名后訂單歷史里還是老名字這就是冗余帶來的不一致。把用空間換時(shí)間和用一致性換便利的取舍講清楚比背誦三大范式定義有用得多。家政項(xiàng)目的業(yè)務(wù)量級(jí)根本到不了需要冗余來提高性能的程度所以干凈的關(guān)系模型是最優(yōu)解。另外課程設(shè)計(jì)里最常見的翻車是把所有字段塞進(jìn)一張大表然后答辯時(shí)講不出這張表的主鍵業(yè)務(wù)含義。家政項(xiàng)目四張表分工明確每一張都能說出為什么存在天然適合答辯。要注意的是表的命名風(fēng)格比如統(tǒng)一用 t_order 還是 order中間不要混用數(shù)據(jù)字典和建表語句對(duì)不上是老師最愛挑的毛病。最后補(bǔ)一個(gè)家政項(xiàng)目特有的邊界真實(shí)平臺(tái)會(huì)接微信支付但畢設(shè)通常開通不了微信支付商戶號(hào)個(gè)人主體沒有資質(zhì)。所以訂單表的amount字段有時(shí)只是存一個(gè)金額沒有真實(shí)的支付回調(diào)鏈路。答辯被問到時(shí)直接說支付環(huán)節(jié)因商戶資質(zhì)限制未接入屬于項(xiàng)目裁剪這是合理做法。如果想加分可以做一個(gè)模擬支付接口前端點(diǎn)立即支付調(diào)后端 mock 接口更新訂單狀態(tài)一句話就能擋住追問。5. 聯(lián)調(diào)避坑SSM 后端對(duì)接小程序的五個(gè)高頻問題后端能啟動(dòng)、小程序能編譯只是通過了入場(chǎng)券。真正花時(shí)間的往往是聯(lián)調(diào)環(huán)節(jié)——小程序發(fā)請(qǐng)求、后端返回結(jié)果、數(shù)據(jù)庫讀寫數(shù)據(jù)整條鏈路一層層查下去。這一章把我自己踩過和幫別人排查過的五個(gè)高頻問題按現(xiàn)象 - 原因 - 解決寫清楚。每一條都不需要?jiǎng)哟笫中g(shù)但對(duì)癥下藥能省出大半天。5.1 數(shù)據(jù)庫中文亂碼頁面顯示問號(hào)的真實(shí)原因現(xiàn)象小程序頁面里服務(wù)名稱、用戶昵稱顯示成問號(hào)或空白。原因這一層層的編碼鏈路里最常出問題的是 MySQL 連接串和建庫字符集。jdbc.properties 里沒有characterEncodingutf8或建庫語句沒有指定 utf8mb4都可能導(dǎo)致亂碼。解決把連接串補(bǔ)全jdbc.urljdbc:mysql://localhost:3306/household?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse同時(shí)確認(rèn)庫表字符集ALTER DATABASE household CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; ALTER TABLE t_order CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;注意順序先改后導(dǎo)。已經(jīng)亂碼的數(shù)據(jù)ALTER 只能保證新數(shù)據(jù)正常舊數(shù)據(jù)修復(fù)不了只能刪了重導(dǎo)。這個(gè)順序問題屬于血淚經(jīng)驗(yàn)我見過有人對(duì)著亂碼數(shù)據(jù)改了三天字符集最后發(fā)現(xiàn)是導(dǎo)庫順序反了。5.2 8080 端口被占用Tomcat 啟動(dòng)失敗的快速處理現(xiàn)象IDEA 啟動(dòng) Tomcat 時(shí)彈窗Port 8080 is already in use或者日志里出現(xiàn)BindException: Address already in use。原因本機(jī)另一個(gè)進(jìn)程占用了 8080常見的是之前啟動(dòng)的 Tomcat 實(shí)例沒有關(guān)干凈或者是別的開發(fā)服務(wù)。解決Windows 在命令行執(zhí)行netstat -ano | findstr 8080 taskkill /pid 12345 /f把12345換成實(shí)際占用的 PID。也可以不改系統(tǒng)層面的端口直接在 IDEA 的 HTTP port 改成 8081一勞永逸。改動(dòng)端口后記得小程序端的 baseUrl 也要同步改前后端端口不一致是聯(lián)調(diào)里最隱蔽的翻車點(diǎn)。提示這是 Windows 下的命令macOS 用lsof -i :8080然后kill PID處理。5.3 小程序報(bào) url not in domain list本地調(diào)試怎么關(guān)校驗(yàn)現(xiàn)象小程序開發(fā)者工具里所有 wx.request 都失敗控制臺(tái)報(bào)url not in domain list。原因微信平臺(tái)規(guī)定小程序 request 的域名必須在后臺(tái)配置到合法域名列表且要求 HTTPS。這是安全機(jī)制正式發(fā)布必須先配置。解決本地聯(lián)調(diào)階段開發(fā)者工具右上角詳情 - 本地設(shè)置 - 勾選不校驗(yàn)合法域名、web-view業(yè)務(wù)域名、TLS 版本以及 HTTPS 證書。真機(jī)預(yù)覽時(shí)手機(jī)上打開小程序后點(diǎn)右上角...選擇開發(fā)調(diào)試。勾選后請(qǐng)求立刻能通這是差別排查里成本最低的一個(gè)開關(guān)。5.4 微信登錄 40029code2session 調(diào)用失敗的三個(gè)可能現(xiàn)象后端請(qǐng)求微信接口返回{errcode:40029,errmsg:invalid code}。原因三個(gè)常見來源——小程序用了錯(cuò)誤的 appidsecret 與 appid 不匹配或者前端同一個(gè) code 被請(qǐng)求了兩次微信的 code 是一次性的。解決第一打開微信公眾平臺(tái)核對(duì)小程序賬號(hào)里的 AppID 和 AppSecret重點(diǎn)是當(dāng)前用的小程序到底是哪個(gè)賬號(hào)。第二后端日志里把請(qǐng)求微信的完整 URL 打出來手動(dòng)拼一下看 secret 末尾有沒有多余的換行或空格。第三前端 wx.login 的回調(diào)里只提交一次不要把 console.log 里打印的 code 再手動(dòng) POST 第二次。40029 還有一個(gè)常見變體 40013那是 appid 本身非法方向不同。5.5 時(shí)間字段變成一串?dāng)?shù)字JSON 序列化日期格式現(xiàn)象后端返回的 createTime 是1718000000000這樣的毫秒時(shí)間戳小程序頁面直接顯示成數(shù)字串。原因SpringMVC 的 Jackson 默認(rèn)把 java.util.Date 序列化為時(shí)間戳。解決在實(shí)體類的日期字段上加注解JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8) private Date createTime;如果項(xiàng)目里日期字段多也可以在 spring-mvc.xml 的注解驅(qū)動(dòng)里配置全局格式。這個(gè)坑不大但演示時(shí)頁面上滿屏數(shù)字會(huì)顯得很業(yè)余建議優(yōu)先處理。另外注意 timezone 不寫的話時(shí)間會(huì)比北京時(shí)間差 8 小時(shí)這是第二個(gè)隱藏點(diǎn)。6. 論文和答辯怎么把這個(gè)項(xiàng)目講成高分十分鐘演示腳本的三個(gè)準(zhǔn)備技巧項(xiàng)目能跑只是拿到了及格線想沖高分論文和答辯這塊才是真正的加分項(xiàng)。這里說三個(gè)我最推薦準(zhǔn)備的技巧全部基于上面幾章已有的內(nèi)容不需要額外做功能。6.1 數(shù)據(jù)字典和 ER 圖讓數(shù)據(jù)庫設(shè)計(jì)章節(jié)對(duì)得上代碼打開論文的數(shù)據(jù)庫設(shè)計(jì)章節(jié)把第 4 章的四張表按字段逐個(gè)核一遍字段名、類型、是否為空、注釋四者必須和 sql 腳本一字不差。ER 圖用 draw.io 重畫導(dǎo)出矢量圖別用截圖。這一章是老師最可能翻閱的地方對(duì)得上第一印象就穩(wěn)了。6.2 十分鐘演示腳本小程序操作和數(shù)據(jù)庫驗(yàn)證交替進(jìn)行演示我建議按下單流程走打開小程序首頁 - 選擇日常保潔 - 填寫地址和時(shí)間 - 提交訂單 - 切到數(shù)據(jù)庫用SELECT * FROM t_order ORDER BY id DESC LIMIT 1;展示新訂單落庫 - 回到小程序刷新訂單列表。整個(gè)鏈路完整走一遍比任何講解都有說服力。注意把 IDEA 的后端日志窗口提前調(diào)出來下單時(shí)讓老師看到接口調(diào)用日志在滾動(dòng)這種活的感覺很加分。6.3 三個(gè)追問預(yù)案登錄態(tài)、訂單并發(fā)、為什么選 SSM老師最愛追問的問題基本集中在微信登錄怎么識(shí)別用戶、兩個(gè)用戶同時(shí)搶同一單怎么保證不沖突、為什么用 SSM 而不是 Spring Boot。前兩個(gè)從第 3 章的 openid 落庫和第 4 章的AND status 0樂觀鎖找答案第三個(gè)只要實(shí)話實(shí)說畢業(yè)設(shè)計(jì)要求指定 SSM且自己熟悉配置過程即可不需要為老框架辯護(hù)。我的習(xí)慣是答辯前一天把演示環(huán)境完整跑一遍重啟兩次電腦再跑一遍。這步操作看起來土但能擋住九成演示事故——至少我見過的現(xiàn)場(chǎng)翻車有一半是前一天沒重啟、第二天 Tomcat 起不來。希望這篇拆解能幫你的家政小程序畢業(yè)設(shè)計(jì)少走彎路把時(shí)間花在真正有分量的地方。本文還有配套的精品資源點(diǎn)擊獲取