全攻略)
簡介一份基于微信小程序與Java后端SSMMySQL的鮮花銷售畢業(yè)設計完整工程包面向計算機相關專業(yè)畢業(yè)生、課程設計及小程序?qū)崙?zhàn)學習者覆蓋管理員、用戶、商家三個角色實現(xiàn)了首頁、鮮花信息與分類管理、訂單及系統(tǒng)管理等核心業(yè)務模塊。整個壓縮包共1341個文件約12.51MB以png圖片、Java源碼、Vue頁面、JavaScript邏輯、wxml/wxss小程序頁面及SQL腳本為主同時包含bat啟動腳本與說明文檔便于直接部署和二次開發(fā)。資源提供完整源碼和數(shù)據(jù)庫其中附帶數(shù)據(jù)庫腳本、構建運行批處理及詳細說明可幫助讀者理解SSM框架在小程序后臺中的應用也能快速跑通前后端聯(lián)調(diào)。目前已有235人學習下載適合需要完整畢業(yè)設計案例和項目實戰(zhàn)經(jīng)驗的人群參考。1. 畢業(yè)設計選它不只是為了“能答辯”這一句又到一年畢設季很多人在選題頁面反復橫跳。如果你手頭拿到的題目是“基于微信小程序java后端的鮮花銷售”先別急著把它歸為“又一套商城系統(tǒng)”。這個項目真正跑通之后你會發(fā)現(xiàn)它把前后端分離、微信登錄、訂單流程、數(shù)據(jù)庫表設計這些面試常問的東西全串起來了。對Java基礎還不算扎實、又想快速擁有一套能演示、能講清楚的項目的人來說它是性價比很高的一個。下面按我實際跑通的路徑來講項目拆解、本地啟動、前后端對接、常見坑以及怎么把它改成你自己的畢設。2. 先把項目拆開看后端、小程序與數(shù)據(jù)庫各管什么拿到壓縮包解壓后不要急著雙擊 README先按“數(shù)據(jù)庫腳本、后端工程、小程序前端”三個目錄去認識它。這類畢設工程的典型結構是一個 Spring Boot 后端提供 RESTful 接口一個原生微信小程序作為前端一個 MySQL 腳本負責初始化數(shù)據(jù)。三者通過 HTTP 接口關聯(lián)數(shù)據(jù)表通過外鍵和業(yè)務邏輯維系。下面把每一塊說清楚免得你后面改的時候不知道動哪里。2.1 管理員端功能清單商品、分類、訂單、輪播是標配后端管理接口對應的是一個管理后臺。雖然這個壓縮包不一定自帶 Vue 后臺頁面但接口層是完整的。常見做法是后端提供一組/admin/**接口管理員登錄后可以對商品做增刪改查、上下架管理商品分類處理訂單狀態(tài)待發(fā)貨、發(fā)貨、完成還能配置首頁輪播圖。我拿到的這份工程里管理員登錄走的是admin表密碼用 MD5 加密存儲初始賬號在 SQL 腳本里就能看到。商品這塊一般包含名稱、主圖、輪播圖列表、詳情富文本或圖片、分類ID、價格、庫存、銷量。這些字段在商品表flower或product里都能對上。訂單表則記錄用戶 ID、收貨地址、總金額、狀態(tài)、下單時間子表order_item存每個商品的數(shù)量和單價。主表負責匯總子表負責明細是標準的一對多設計。分類表通常很簡單id、名稱、圖片、排序號。輪播圖表也是 id、圖片、跳轉鏈接。所以如果你調(diào)研需求會發(fā)現(xiàn)“鮮花銷售”本質(zhì)上就是一個通用商城把商品名詞換掉就能套用到其他垂直品類。這也是為什么這類項目容易被改造成蛋糕店、零食店、二手交易。答辯時你把這一層講清楚老師就知道你不是只會照抄。2.2 用戶端小程序登錄、瀏覽、加購、下單一條線用戶端是原生微信小程序頁面大概包括首頁輪播分類入口商品列表、分類頁、商品詳情頁、購物車頁、確認訂單頁、訂單列表頁、個人中心頁。邏輯上是一條完整鏈路用戶打開首頁看商品點進詳情加入購物車結算下單模擬支付然后在訂單列表看到狀態(tài)變化。這一步覆蓋了小程序開發(fā)里最核心的頁面?zhèn)鲄ⅰ⒈镜鼐彺?、請求封裝和組件復用。登錄部分小程序端用wx.login拿code傳給后端后端替小程序向微信服務器換openid然后生成自定義 token 返回給前端。有些版本還會調(diào)getPhoneNumber組件獲取手機號但注意這個接口需要小程序認證為企業(yè)主體個人主體沒法用這點在避坑章節(jié)再強調(diào)。購物車數(shù)據(jù)通常存在后端表里cart表也有簡化版存在本地wx.setStorageSync里。這份工程既然帶了數(shù)據(jù)庫多半走的是后端購物車。這樣訂單表直接引用購物車數(shù)據(jù)生成邏輯閉環(huán)更完整。如果你拿到的版本是本地購物車也無妨但要注意換設備后購物車會丟答辯時可以提一句這是簡化方案。2.3 數(shù)據(jù)庫設計概覽五張核心表怎么關聯(lián)打開 SQL 腳本重點看這幾張表表名核心字段作用adminid, username, password管理員登錄userid, openid, nickname, avatar, phone用戶信息categoryid, name, sort商品分類flowerid, category_id, name, price, stock, image, detail商品主體cartid, user_id, flower_id, quantity, checked購物車orderid, order_no, user_id, total_amount, status, address_id訂單主表order_itemid, order_id, flower_id, quantity, price訂單明細bannerid, image, link首頁輪播關系很好懂user與order是一對多order與order_item是一對多flower與category是多對一。購物車里一條記錄對應一個用戶和一個商品。這種設計是教科書級別的范式不花哨但適合答辯——老師問外鍵、索引、三范式你都能指著表回答。這里有一個細節(jié)訂單金額在order表里冗余了一份而不是每次都去order_item里 sum。這在商城系統(tǒng)里是常見做法因為訂單生成后商品價格可能變動必須把下單那一刻的金額快照保存下來。面試如果被問到“商品改價了老訂單怎么算”答案就在這里。另外商品表flower我一般建議多一個status字段0 下架 1 上架和sales字段銷量這兩列在畢設演示中非常有用。下架商品在前端列表不展示銷量可以在商品詳情頁展示。SQL 腳本里如果缺少自己ALTER TABLE補上即可不影響原邏輯。數(shù)據(jù)庫字符集一般設置成utf8mb4否則表情符號存不進去。商品名稱、用戶昵稱里可能出現(xiàn) emoji用utf8會報錯或變問號。稍后避坑章節(jié)再展開。3. 從本地跑起來JDK、MySQL與微信開發(fā)者工具的三步順序很多人拿到源碼第一步就卡在環(huán)境上。這個項目我建議按“后端→數(shù)據(jù)庫→小程序”的順序依次啟動每一步驗證通過再進下一步不要在沒跑通后端的情況下就去點小程序不然接口報錯你會分不清是前端問題還是后端問題。3.1 Spring Boot 后端啟動前的環(huán)境準備這類項目的后端技術棧基本是 Spring Boot 2.x MyBatis / MyBatis-Plus Maven。打開pom.xml確認依賴版本。建議用 JDK 1.8Spring Boot 2.x 搭配很穩(wěn)如果裝了 JDK 17有些舊依賴會因javax命名空間問題加載失敗。我一般會在 IDEA 里把 Project Structure 里的 SDK 切到 1.8Maven Runner 里的 JRE 也選 1.8避免編譯期報錯。啟動前要在 IDEA 里做兩件事一是確認 Maven 已經(jīng)配了阿里云鏡像否則下載依賴能磨掉你半小時耐心二是打開application.yml看一眼端口和數(shù)據(jù)源配置。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/flower_shop?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的數(shù)據(jù)庫密碼 driver-class-name: com.mysql.cj.jdbc.Driver這里的serverTimezoneAsia/Shanghai很關鍵MySQL 8 以上不寫它連接時大概率報時區(qū)錯誤。characterEncodingutf8則保證中文正常寫入。如果你的 MySQL 是 5.7驅(qū)動用com.mysql.jdbc.Driver也行但新版工程一般都用cj驅(qū)動。參數(shù)說明useUnicodetrue讓驅(qū)動按 Unicode 傳輸字符配合characterEncodingutf8才能保證中文不亂碼。MySQL 8 建議用utf8mb4但驅(qū)動對utf8兼容。啟動方式有兩種IDEA 里直接運行Application.java的 main 方法或命令行mvn spring-boot:run??刂婆_出現(xiàn)Started Application in x.xxx seconds且沒有紅色異常就說明后端起來了。此時瀏覽器訪問http://localhost:8080/api/xxx具體路徑看 Controller 注解能看到 JSON說明接口正常。3.2 導入數(shù)據(jù)庫腳本并核對賬號配置數(shù)據(jù)庫腳本一般在工程根的sql目錄下文件名類似flower_shop.sql。用 Navicat 或命令行導入。命令行導入命令mysql -uroot -p flower_shop.sql導入后執(zhí)行show tables;你應該能看到 8 張左右的表。如果一張表都沒看到檢查 SQL 腳本里是否帶了CREATE DATABASE flower_shop而當前登錄用戶沒有建庫權限。常見做法是腳本里有建庫語句導入后要切換庫use flower_shop;。這里有一個容易忽略的點腳本里的管理員初始密碼是加密后的 MD5 值除非你知道原始密碼否則不要直接改admin表的 password 字段。登錄不了后臺時最穩(wěn)妥的辦法是找代碼里的MD5Util或DigestUtils手動把新密碼加密后 update 進表。我見過太多人直接把這個字段改成明文然后卡在“密碼錯誤”上花半天找原因。另外檢查application.yml里的數(shù)據(jù)庫名、用戶名、密碼是否與本地一致。數(shù)據(jù)庫名一般是flower_shop如果腳本里建庫名不一樣要么改 yml要么改腳本二選一不要兩處都留著不同。你可以用DESC user;看下表結構驗證腳本是否完整。如果表里已經(jīng)帶了測試數(shù)據(jù)啟動后首頁就會有商品省得自己造數(shù)。3.3 小程序端導入微信開發(fā)者工具后端和數(shù)據(jù)庫都就緒后打開微信開發(fā)者工具選擇“導入項目”目錄指向小程序端文件夾通常叫miniprogram或frontend。這里需要兩個關鍵配置一是你自己的測試 AppID如果沒有用測試號也可以但登錄相關功能受限二是本地開發(fā)時在“詳情→本地設置”里勾選“不校驗合法域名、web-view業(yè)務域名、TLS 版本以及 HTTPS 證書”。小程序端的請求地址一般在utils/config.js或app.js里常見寫法const BASE_URL http://127.0.0.1:8080/api; module.exports { BASE_URL }注意微信開發(fā)者工具里請求localhost有時會因 IPv6 解析慢建議直接用127.0.0.1。如果你后端起在別的機器或云上這里就要改成服務器 IP 或域名并配好微信后臺的 request 合法域名。本地開發(fā)勾選不校驗域名就行但真機預覽時手機無法訪問你電腦的localhost需要把后端部署到可訪問的服務器或者用內(nèi)網(wǎng)穿透工具這里不展開。導入后編譯如果看到首頁輪播圖和商品列表都出來了說明前后端已經(jīng)打通。如果商品列表空白打開調(diào)試器看 Console 報錯最常見的是請求 404 或請求被攔截。還有一個適配問題如果頁面頂部出現(xiàn)重影或按鈕和膠囊重疊是因為自定義導航欄沒有適配狀態(tài)欄高度。通常用wx.getSystemInfoSync()獲取statusBarHeight再用wx.getMenuButtonBoundingClientRect()拿到膠囊的位置動態(tài)計算導航欄高度才能保證在劉海屏和普通屏上都不錯位。4. 小程序與Java后端聯(lián)調(diào)登錄換取openid與Token鑒權這一章是畢設答辯的重頭戲。老師問“怎么知道你登錄了”“接口安全怎么做的”你只要能說清楚登錄時序和 token 校驗基本就能過關。下面按實際代碼路徑講。4.1 wx.login 拿到 code后端換 openid 的流程小程序端點擊微信登錄時調(diào)用wx.login獲取一個臨時憑證code這個 code 只能使用一次有效期五分鐘。把 code 通過接口 POST 給后端后端拿著 code 去微信接口jscode2session換取openid和session_key。openid 是用戶在微信體系下的唯一 ID用它去user表里查查不到就注冊新用戶。后端代碼如下偽代碼邏輯具體類名以源碼為準PostMapping(/auth/login) public Result login(RequestBody LoginRequest req) { // 1. 用小程序的 appid 和 secret以及前端傳的 code請求微信接口 String url https://api.weixin.qq.com/sns/jscode2session?appid APPID secret SECRET js_code req.getCode() grant_typeauthorization_code; String response HttpUtil.get(url); // 2. 解析返回的 openid JSONObject obj JSON.parseObject(response); String openid obj.getString(openid); // 3. 查表沒有則注冊 User user userMapper.selectByOpenid(openid); if (user null) { user new User(); user.setOpenid(openid); userMapper.insert(user); } // 4. 生成自己的登錄態(tài) token String token UUID.randomUUID().toString().replace(-, ); redis.set(token_ token, String.valueOf(user.getId()), 7 * 24 * 3600); return Result.success(token); }邏輯說明后端不信任前端傳來的任何身份信息只用code向微信服務器兌換身份這是安全邊界的第一條。grant_typeauthorization_code是固定值表示 OAuth2 授權碼模式。如果你沒有 Redis也可以用session或直接返回token并存在內(nèi)存 Map 里但項目重啟就失效畢設夠用答辯時記得說明缺點。參數(shù)說明APPID和SECRET在小程序后臺的“開發(fā)→開發(fā)管理→開發(fā)設置”里獲取。注意 SECRET 不要硬編碼在 Web 端也不要在小程序代碼里出現(xiàn)否則任何人都能拿去調(diào)用接口。我見過源碼里把這兩個值寫在util.js里的這種做法答辯時會被扣分至少把它挪到后端配置里。小程序端對應代碼wx.login({ success: async (res) { const code res.code; const loginRes await request({ url: /auth/login, method: POST, data: { code: code } }); wx.setStorageSync(token, loginRes.data.token); } })這里把token存到本地緩存后續(xù)每個請求在 header 里帶上Authorization: token后端攔截器統(tǒng)一校驗。4.2 前后端分離項目的接口路徑與參數(shù)約定后端 Controller 一般會分成兩類用戶端/api/**和管理端/admin/**。用戶端接口例如GET /api/banner、GET /api/flower/list?categoryId1、POST /api/cart/add、POST /api/order/submit。管理端需要管理員身份通常會有一個/admin/login登錄后返回管理員 token后續(xù)管理操作攜帶該 token。統(tǒng)一返回格式非常重要推薦約定成{ code: 0, message: success, data: { } }code0表示成功非 0 為業(yè)務異常。前端在request封裝里統(tǒng)一攔截function request(options) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, Authorization: wx.getStorageSync(token) || }, success: (res) { if (res.data.code 0) { resolve(res.data); } else { wx.showToast({ title: res.data.message, icon: none }); reject(res.data); } }, fail: (err) reject(err) }) }) }這段封裝的價值在于所有頁面不用關心 token 怎么傳統(tǒng)一在 header 里帶所有后端返回的錯誤在success回調(diào)里統(tǒng)一彈 toast。頁面代碼只管調(diào)用request不需要散落一堆try/catch。參數(shù)說明BASE_URL不要寫在每個頁面里url以/開頭拼接。如果你遇到“接口通了但登錄不了”優(yōu)先檢查 header 里的 token 名是否和后端攔截器取的 header 名一致。4.3 常見做法用 Token 還是 Session 做認證微信小程序沒有 Cookie 概念所以傳統(tǒng) Session 方式要么手動把JSESSIONID存起來再傳要么干脆用 Token。Token 方案在前后端分離項目里是主流畢設中用起來也簡單登錄成功后返回一個隨機字符串后端用一個 Map 或 Redis 存這個 token 對應的用戶 ID下一次請求帶著 token后端查 Map 就知道是誰。Component public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); if (token null || token.isEmpty()) { response.setStatus(401); return false; } String userId tokenStore.get(token); if (userId null) { response.setStatus(401); return false; } request.setAttribute(userId, userId); return true; } }這個攔截器要注冊到 WebMvcConfigurer 里并排除登錄接口和商品瀏覽接口否則游客沒有 token連商品列表都看不了。參數(shù)說明tokenStore是一個MapString, String生產(chǎn)環(huán)境應該換成 Redis 并設置過期時間。答辯時老師如果問“你的 token 永遠不會過期嗎”你回答“目前用內(nèi)存存儲重啟失效生產(chǎn)環(huán)境會替換為 Redis 并設置 7 天過期”就是一次不錯的追問應對。管理端接口建議單獨寫一個AdminAuthInterceptor不能和用戶端共用同一個 token 存儲。管理員的 token 要有獨立的過期機制否則普通用戶偽造 token 就能調(diào)用后臺接口。5. 避坑與常見問題五個最讓人翻車的點這一章是我跑這類畢設項目時的血淚經(jīng)驗匯總每一條都是真實發(fā)生過的。按“現(xiàn)象→原因→解決”的順序?qū)懩阏罩挪槟苁“胩鞎r間。5.1 現(xiàn)象微信開發(fā)者工具請求后端接口報“不在以下合法域名列表中”原因微信小程序出于安全考慮要求所有wx.request的域名必須是 HTTPS 且在后臺配置過。本地開發(fā)時后端是http://127.0.0.1:8080肯定不滿足。解決開發(fā)階段在微信開發(fā)者工具右上角“詳情→本地設置”勾選“不校驗合法域名”。真機預覽時沒有這個選項要么把后端部署到帶 HTTPS 的服務器并配置域名要么用內(nèi)網(wǎng)穿透。注意勾選后要重新編譯。如果依然報錯檢查BASE_URL里是否帶了/api后又拼接了/api形成/api/api雙前綴。這種玄學問題最費時間建議先打印實際請求的完整 URL。5.2 現(xiàn)象數(shù)據(jù)庫導入后中文亂碼商品名稱變成“???”原因?qū)?SQL 腳本時客戶端連接字符集不是 UTF-8或者腳本本身的編碼是 GBK。最典型的是用命令行導入時沒加--default-character-setutf8mb4。解決重新導入并顯式指定字符集mysql -uroot -p --default-character-setutf8mb4 flower_shop.sql如果已經(jīng)導入了可以改表字符集ALTER TABLE flower CONVERT TO CHARACTER SET utf8mb4;同時檢查application.yml里的連接串是否有characterEncodingutf8并確認 MySQL 的my.cnf里[client]和[mysqld]都設置了default-character-setutf8mb4。改完重啟后端重新查一遍數(shù)據(jù)才有意義。這里多說一句你看到源碼里中文正常不代表你本地復制過來也正常編碼問題要最先查。5.3 現(xiàn)象商品圖片上傳后小程序端顯示不出來原因圖片路徑存的是絕對路徑比如D:\upload\1.jpg或者存的是沒有帶域名的相對路徑但后端配置了虛擬路徑映射。前端拿到\upload\1.jpg拼上BASE_URL后變成http://127.0.0.1:8080/api/upload/1.jpg而后端靜態(tài)資源映射路徑是/upload/**映射到磁盤目錄接口前綴/api把路徑吃掉了。解決第一后端存圖片時只存相對路徑/upload/xxx.jpg不要存絕對路徑。第二靜態(tài)資源映射配置要確認攔截路徑。Spring Boot 中常見做法Configuration public class WebConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file:D:/upload/); } }這里的file:D:/upload/是圖片在服務器本地的物理路徑注意結尾要有/。如果你把圖片放在項目目錄下推薦用file:./upload/這種相對寫法避免部署到別的機器還要改路徑。前端拼圖片地址時我一般會讓后端直接返回完整 URL也就是在序列化商品對象時把image字段加工成http://ip:8080/upload/...。源碼里如果沒這么做前端拼的時候要小心雙斜杠問題。5.4 現(xiàn)象并發(fā)下單時庫存變成負數(shù)訂單和庫存對不上原因下單邏輯是“查詢庫存→判斷充足→UPDATE庫存→插入訂單”中間沒有事務和鎖。兩個人同時買同一款鮮花都讀到庫存 5各自減 1UPDATE 最終是 4但實際上應該賣出 2 單。更糟的是如果訂單插入失敗庫存已經(jīng)減了但訂單沒生成數(shù)據(jù)不一致。解決在 Service 方法上加Transactional并且用樂觀鎖或悲觀鎖控制庫存更新。最簡單的做法是 UPDATE 語句里加上庫存條件UPDATE flower SET stock stock - 1 WHERE id ? AND stock 0如果影響行數(shù)為 0說明庫存不足直接拋業(yè)務異?;貪L訂單。同時Transactional保證扣庫存和插訂單在同一個事務里任何一步失敗都回滾。代碼示意Transactional(rollbackFor Exception.class) public Order submitOrder(SubmitRequest req) { // 1. 扣庫存受影響行數(shù)為0則拋異常 int rows flowerMapper.deductStock(req.getFlowerId(), req.getQuantity()); if (rows 0) { throw new BusinessException(庫存不足); } // 2. 創(chuàng)建訂單主表和明細表 // 3. 返回訂單對象 }參數(shù)說明rollbackFor Exception.class很關鍵只寫Transactional默認只回滾 RuntimeExceptionchecked exception比如IOException會導致庫存扣了但訂單沒建這就是經(jīng)典的血淚坑。5.5 現(xiàn)象個人版小程序獲取手機號按鈕功能點擊無效原因button open-typegetPhoneNumber這個能力需要小程序主體是企業(yè)或個體工商戶個人主體的小程序無法調(diào)用點擊按鈕會收到getPhoneNumber:fail no permission或類似錯誤。很多簡歷上寫了“獲取用戶手機號”但用個人 AppID 演示時直接翻車。解決如果只是做畢設演示建議把手機號獲取改成可編輯的輸入框讓用戶手動填接口里校驗 11 位格式?;蛘呱暾堃粋€企業(yè)主體小程序?qū)W生可借用實驗室、導師公司的資質(zhì)才能完整走通。答辯時把這一點提前說明個人開發(fā)者無法使用該接口所以才退化為手動輸入這是合規(guī)做法不是偷懶。如果源碼里已經(jīng)使用了getPhoneNumber你拿到后不要硬調(diào)先把該功能隱藏避免現(xiàn)場爆紅。6. 改造成你自己的畢設換主題、加狀態(tài)機與交付習慣前面幾章解決了“跑起來”和“避坑”最后一章講怎么把它變成“你的項目”。畢竟答辯時老師會問你做了什么如果你回答“把鮮花換成了蛋糕”那至少說明你理解了項目的可維護性。6.1 替換商品分類、圖片與文案的最快路徑打開數(shù)據(jù)庫category表里把“鮮花”“綠植”改成你的主題分類比如“蛋糕”“甜品”“烘焙工具”。flower表里的商品名稱、圖片 URL、價格、庫存都改成你自己的數(shù)據(jù)。圖片資源直接替換upload目錄下的文件保持原文件名映射最省事。小程序端的頁面文案在pages目錄下的.wxml文件里搜索“鮮花”關鍵字全局替換。改完這幾處項目主題就變了前后端邏輯一行不用動。建議做一張“替換清單”表格把需要改的位置列出來相當于一份自定義文檔。答辯時拿出這個比只會說“我改了圖片”要有說服力得多。6.2 給畢設答辯加分的驗證點訂單狀態(tài)機原項目訂單狀態(tài)可能只是簡單的下拉框選擇。你可以把它升級成狀態(tài)機待付款→待發(fā)貨→已發(fā)貨→已完成以及取消、退款兩個分支。后端用一張狀態(tài)枚舉表維護前端根據(jù)狀態(tài)顯示按鈕。實現(xiàn)并不難但在代碼里體現(xiàn)“狀態(tài)流轉”的概念能讓評委覺得你有工程意識。public enum OrderStatusEnum { WAIT_PAY(0, 待付款), WAIT_SHIP(1, 待發(fā)貨), SHIPPED(2, 已發(fā)貨), FINISHED(3, 已完成), CANCELLED(4, 已取消); // 構造方法、getter... }在order表增加一個字段或者直接復用原 status 字段把 update 操作封裝成changeStatus(orderId, fromStatus, toStatus)如果當前狀態(tài)不是fromStatus就拋異常。用這套邏輯把之前簡單 update 的代碼替換掉項目深度至少提升一個檔次。6.3 動手前先備份改完每個點都要回歸最后說一個我自己的習慣。每次拿到新的畢設源碼第一件事不是雙擊運行而是先看數(shù)據(jù)庫腳本和配置文件再啟動項目。任何一次改動之前我都會先備份一份原始代碼哪怕只是改一個字段名。從那以后我每次跑這類項目都會把“后端啟動→小程序編譯→下單流程”強制走一遍確認沒有回歸問題再繼續(xù)下一步。希望幫到你。本文還有配套的精品資源點擊獲取