餐系統(tǒng)畢業(yè)設(shè)計(jì)攻略:SpringBoot+Vue前后端分離實(shí)戰(zhàn))
1. 選題思路與整體技術(shù)架構(gòu)1.1 為什么點(diǎn)餐系統(tǒng)適合做畢業(yè)設(shè)計(jì)這幾年指導(dǎo)過的畢業(yè)設(shè)計(jì)里點(diǎn)餐系統(tǒng)幾乎是“常青樹”選題。原因很直接業(yè)務(wù)模型完整但不過度復(fù)雜恰好覆蓋了前后端分離開發(fā)的大部分核心知識點(diǎn)。一個(gè)用戶能注冊登錄、瀏覽菜品、加購物車、下單付款管理員能維護(hù)菜品、處理訂單這套流程足夠撐起一篇有含金量的論文又不會(huì)像電商系統(tǒng)那樣為了湊復(fù)雜度硬塞一堆用不上的模塊。關(guān)鍵要清楚點(diǎn)餐系統(tǒng)不是“做個(gè)網(wǎng)頁賣飯”它的本質(zhì)是一套交易系統(tǒng)的簡化模型。要處理的核心問題包括用戶身份認(rèn)證、商品數(shù)據(jù)管理、訂單狀態(tài)流轉(zhuǎn)、庫存一致性、支付回調(diào)處理模擬即可、并發(fā)場景下的數(shù)據(jù)安全。把這些點(diǎn)想明白寫論文和答辯時(shí)才有東西可講不是對著界面截圖干說“我做了個(gè)網(wǎng)站”。技術(shù)棧選SpringBootVue是目前最穩(wěn)妥的組合。SpringBoot生態(tài)成熟、資料多、招人問得多Vue對新手友好、組件化開發(fā)直觀。前后端分離也是真實(shí)企業(yè)開發(fā)的主流形態(tài)做完這套東西拿得出手的技能棧比用JSPServlet老方案的同學(xué)明顯扎實(shí)一截。1.2 整體架構(gòu)和模塊劃分系統(tǒng)按常見的“用戶端管理端”雙端設(shè)計(jì)這是點(diǎn)餐系統(tǒng)的標(biāo)準(zhǔn)切法。用戶端核心模塊包括注冊登錄、菜品瀏覽與分類篩選、購物車管理、訂單提交與支付模擬、訂單歷史查詢、個(gè)人資料修改。管理端核心模塊包括管理員登錄、菜品CRUD增刪改查、分類管理、訂單處理接單/完成/取消、簡單的數(shù)據(jù)統(tǒng)計(jì)。前后端如何劃分是重點(diǎn)。SpringBoot只負(fù)責(zé)提供RESTful API接口不返回任何頁面Vue負(fù)責(zé)渲染界面、交互邏輯、路由跳轉(zhuǎn)。兩邊通過JSON格式的數(shù)據(jù)交互。這里要特別強(qiáng)調(diào)一個(gè)觀念前端是“展示層輕邏輯”后端是“數(shù)據(jù)層核心業(yè)務(wù)規(guī)則”。比如“下單”這個(gè)動(dòng)作前端做的事情是收集購物車數(shù)據(jù)、請求下單接口、展示結(jié)果而“庫存是否足夠”“訂單狀態(tài)是否允許取消”這類規(guī)則判斷必須放在后端絕不能依賴前端傳參或前端判斷。數(shù)據(jù)庫設(shè)計(jì)上核心表不用多但每張都要有存在價(jià)值。我通常建議至少五張表用戶表user、菜品分類表category、菜品表dish、訂單表orders、訂單明細(xì)表order_detail外加購物車表cart和可選的地址表address。重點(diǎn)說下訂單和訂單明細(xì)為什么要拆兩張表一個(gè)訂單包含多個(gè)菜品如果把菜品信息直接塞進(jìn)訂單表一個(gè)字段存多個(gè)菜品ID查詢、統(tǒng)計(jì)、修改都極其痛苦。拆成明細(xì)表后訂單主表只存訂單總額、狀態(tài)、時(shí)間這些訂單級信息明細(xì)表每個(gè)菜品一行記錄綁訂單ID。這也是工作中最基礎(chǔ)的表設(shè)計(jì)訓(xùn)練。1.3 技術(shù)選型背后的取舍邏輯單純羅列技術(shù)棧沒有意義重要的是知道為什么這么選。后端SpringBoot選2.x版本而不是3.x主要考慮生態(tài)兼容性。3.x要求JDK17起步很多教材、博客、開源工具還停留在舊版本畢設(shè)階段沒必要在這上面給自己挖坑。SpringBoot 2.7.x JDK8或JDK11穩(wěn)定且資料多出問題一搜就有答案。持久層框架在MyBatis-Plus和Spring Data JPA之間我更推薦MyBatis-Plus。原因很實(shí)際點(diǎn)餐系統(tǒng)的SQL大多是單表CRUD和簡單的多表聯(lián)查MyBatis-Plus的BaseMapper直接幫你把增刪改查寫完了省下大量重復(fù)代碼。條件構(gòu)造器做動(dòng)態(tài)查詢也很順手。JPA雖然開發(fā)效率同樣不低但關(guān)聯(lián)關(guān)系配置和懶加載的坑對新手不夠友好調(diào)試成本高。前端Vue選Vue2還是Vue3要慎重。如果現(xiàn)在開始做建議直接上Vue3 Element Plus。Vue3是當(dāng)前主流Vue2生態(tài)已經(jīng)停止維護(hù)做畢設(shè)沒必要用馬上過時(shí)的技術(shù)。組合式API剛開始寫可能不習(xí)慣但堅(jiān)持寫兩周就會(huì)覺得比選項(xiàng)式API更適合邏輯復(fù)用。配套的Element Plus做后臺管理界面非??毂砀?、表單、彈窗都是現(xiàn)成組件顏值也在線。數(shù)據(jù)庫無腦選MySQL版本8.0以上。開發(fā)環(huán)境用Navicat或DataGrip管理數(shù)據(jù)庫本地跑就行不需要單獨(dú)裝服務(wù)器。2. 后端核心模塊設(shè)計(jì)與關(guān)鍵細(xì)節(jié)2.1 用戶認(rèn)證從Session到JWT用戶認(rèn)證是幾乎所有系統(tǒng)第一個(gè)要解決的問題。點(diǎn)餐系統(tǒng)用戶端要登錄管理端也必須登錄但兩者權(quán)限不同這就涉及權(quán)限區(qū)分。傳統(tǒng)做法是SessionCookie服務(wù)器存會(huì)話返回一個(gè)SessionId給瀏覽器。前后端分離的架構(gòu)下更推薦用JWTJSON Web Token。核心邏輯是用戶登錄成功后后端用密鑰生成一個(gè)包含用戶信息的加密Token返回給前端前端每次請求帶著Token后端驗(yàn)簽確認(rèn)身份。這樣做的好處是服務(wù)器無狀態(tài)不用維護(hù)會(huì)話記錄非常適合多端瀏覽器、手機(jī)接入的場景缺點(diǎn)是Token如果被盜用在過期之前都能被使用所以一定要設(shè)置合理的過期時(shí)間。具體實(shí)現(xiàn)用現(xiàn)成工具不需要自己手寫加密邏輯。引入jjwt依賴寫一個(gè)JwtUtil工具類包含三個(gè)核心方法生成Token、解析Token、判斷Token是否有效。Token里放什么信息有講究我習(xí)慣只放用戶ID、用戶名、角色不放密碼等敏感數(shù)據(jù)。權(quán)限控制怎么做是關(guān)鍵。寫一個(gè)攔截器實(shí)現(xiàn)HandlerInterceptor接口在preHandle方法里從請求頭取Authorization字段解析Token成功了放行失敗了返回401狀態(tài)碼。然后寫一個(gè)WebMvcConfigurer配置類注冊攔截器并指定攔截路徑——管理端接口全攔截用戶端部分接口攔截。有一個(gè)常見問題是前后端聯(lián)調(diào)時(shí)前端因?yàn)轫憫?yīng)攔截器處理不當(dāng)Token失效時(shí)頁面不跳轉(zhuǎn)登錄頁而是停留在當(dāng)前頁面報(bào)錯(cuò)這個(gè)后面排查部分會(huì)提到。2.2 菜品管理與文件上傳的取舍菜品管理是管理端最基礎(chǔ)的功能核心是CRUD加上傳菜品圖片。大多數(shù)學(xué)生在這里犯的第一個(gè)錯(cuò)誤是沒有區(qū)分“邏輯刪除”和“物理刪除”。刪除菜品如果直接從數(shù)據(jù)庫DELETE數(shù)據(jù)的完整性就破壞了。比如用戶已經(jīng)下過單訂單詳情關(guān)聯(lián)了菜品ID菜品被刪了訂單歷史查詢就會(huì)關(guān)聯(lián)失敗。生產(chǎn)環(huán)境幾乎都是邏輯刪除——給表加一個(gè)status字段1表示正常、0表示刪除刪除操作只是把status改成0查詢時(shí)默認(rèn)過濾掉。MyBatis-Plus支持TableLogic注解配置后deleteById方法自動(dòng)變成update語句非常方便。圖片上傳這塊SpringBoot接收MultipartFile保存到本地指定目錄然后返回圖片的URL路徑。這里要注意兩點(diǎn)一個(gè)是保存路徑不要寫死絕對路徑用配置項(xiàng)維護(hù)方便換環(huán)境另一個(gè)是URL映射配置。默認(rèn)情況下SpringBoot訪問不到本地磁盤的文件需要寫一個(gè)配置類繼承WebMvcConfigurer重寫addResourceHandlers方法把虛擬路徑/api/image/**映射到真實(shí)存儲目錄。這個(gè)坑幾乎每個(gè)學(xué)生都踩一次報(bào)404或圖片不顯示八成就是這里沒配。菜品分頁查詢直接使用MyBatis-Plus的Page對象配合LambdaQueryWrapper做條件篩選。管理端查詢可以按分類篩選、按狀態(tài)篩選、按名稱模糊查詢這些條件組合也是前端篩選組件的數(shù)據(jù)來源。需要注意分頁參數(shù)要單獨(dú)封裝一個(gè)PageQuery對象而不是Map接收這樣前端傳參結(jié)構(gòu)清晰后端參數(shù)校驗(yàn)也好做。2.3 購物車與訂單事務(wù)與狀態(tài)機(jī)購物車其實(shí)就是一個(gè)臨時(shí)存儲數(shù)據(jù)的過程表結(jié)構(gòu)相對固定主鍵、用戶ID、菜品ID、數(shù)量、加購時(shí)間。還要冗余一個(gè)菜品名稱和單價(jià)字段這樣購物車列表展示時(shí)不需要聯(lián)查菜品表性能好萬一菜品被刪了也不影響購物車歷史數(shù)據(jù)的展示。訂單模塊是整個(gè)系統(tǒng)的重量級模塊也是最容易出問題的部分。下單接口的流程是前端傳來購物車數(shù)據(jù)后端校驗(yàn)每個(gè)菜品是否存在、狀態(tài)是否正常然后計(jì)算總價(jià)創(chuàng)建訂單主記錄再循環(huán)插入訂單明細(xì)最后清空購物車。這里必須加事務(wù)注解Transactional保證“創(chuàng)建訂單、插入明細(xì)、清空購物車”三個(gè)操作要么全部成功、要么全部失敗。不加事務(wù)的后果就是訂單建了明細(xì)沒插進(jìn)去或者明細(xì)插了購物車沒清掉演示的時(shí)候特別尷尬。庫存扣減也是畢設(shè)答辯容易追問的點(diǎn)。我當(dāng)時(shí)做的是下單時(shí)判斷菜品是否還有庫存夠則扣減不夠則提示菜品已售罄。這個(gè)邏輯看起來沒問題但并發(fā)場景下會(huì)出問題——兩個(gè)用戶同時(shí)下單同一個(gè)菜都查到了庫存為1都執(zhí)行扣減結(jié)果庫存變成-1。解決方案是扣庫存時(shí)要使用樂觀鎖加一個(gè)version字段執(zhí)行update時(shí)要帶上版本條件影響行數(shù)為0則說明已經(jīng)被別人改過了報(bào)錯(cuò)重試。雖然畢設(shè)項(xiàng)目的并發(fā)量達(dá)不到這么極端但把這套邏輯說出來答辯時(shí)就是加分項(xiàng)。訂單狀態(tài)我用一個(gè)整數(shù)類型status字段表示定義一個(gè)狀態(tài)枚舉類1表示待支付、2表示已支付/待接單、3表示制作中/已接單、4表示已完成、5表示已取消、6表示已退款。為什么不用字符串一方面存儲空間小查詢快另一方面狀態(tài)定義集中在枚舉類里不會(huì)出現(xiàn)各處魔法數(shù)字滿天飛的情況。狀態(tài)流轉(zhuǎn)必須有嚴(yán)格的規(guī)則比如已完成的訂單不能再取消已取消的不能再接單這些判斷邏輯放在Service層接口層不做任何業(yè)務(wù)判斷。2.4 數(shù)據(jù)統(tǒng)計(jì)怎么做到簡單但有用管理端首頁放幾個(gè)數(shù)據(jù)卡片是很多畢設(shè)的標(biāo)配。銷量統(tǒng)計(jì)、營業(yè)額、熱銷菜品排名這些數(shù)據(jù)看起來復(fù)雜其實(shí)SQL幾行就能寫出來。關(guān)鍵是用對聚合函數(shù)和分組。日營業(yè)額就是按日期分組求和訂單金額限定訂單狀態(tài)不是“已取消”的。熱銷菜品要關(guān)聯(lián)訂單明細(xì)表按菜品ID分組SUM數(shù)量倒序排LIMIT取前十。注意做統(tǒng)計(jì)查詢時(shí)日期范圍通常用前端傳參控制后端只負(fù)責(zé)接收開始日期和結(jié)束日期在Service層組裝SQL條件。這個(gè)模塊不需要做得太重簡單幾組圖表就夠。真正想加分的話可以做一張每日訂單量趨勢圖前端用ECharts的折線圖展示后端寫一個(gè)接口返回最近七天的訂單數(shù)和營業(yè)額。講明白“按時(shí)間粒度聚合”的思路就是一篇可圈可點(diǎn)的設(shè)計(jì)說明。3. 前端工程與核心界面實(shí)現(xiàn)3.1 Vue3工程結(jié)構(gòu)和基礎(chǔ)設(shè)施搭建前端工程用Vite構(gòu)建比Webpack快的不是一點(diǎn)半點(diǎn)配置也極簡。項(xiàng)目結(jié)構(gòu)我習(xí)慣分四塊src/api放接口請求封裝、src/router放路由配置、src/store放全局狀態(tài)、src/views放頁面組件另外src/components放公共組件、src/utils放工具函數(shù)。路由設(shè)計(jì)要區(qū)分用戶端和管理端。用戶端包括登錄注冊頁、點(diǎn)餐首頁、菜品分類頁、購物車頁、訂單確認(rèn)頁、訂單列表頁、個(gè)人中心頁管理端包括登錄頁、系統(tǒng)布局頁側(cè)邊欄頂欄、菜品管理頁、分類管理頁、訂單管理頁、數(shù)據(jù)統(tǒng)計(jì)頁。這里要注意嵌套路由的用法管理端子頁面都套在一個(gè)Layout組件下面?zhèn)冗厵诤晚敊诓挥弥貜?fù)寫。路由守衛(wèi)是每個(gè)前端項(xiàng)目必須處理的環(huán)節(jié)。Vue Router提供了beforeEach導(dǎo)航守衛(wèi)在跳轉(zhuǎn)之前判斷用戶是否有權(quán)訪問目標(biāo)路由。邏輯是檢查目標(biāo)路由的meta是否需要登錄需要的話再檢查本地存儲有沒有Token沒有就跳登錄頁。如果是管理端路由還要額外檢查用戶角色是否為管理員。這個(gè)邏輯看起來不復(fù)雜但它決定了前端的“第一道安全門”雖然不是真正的安全但至少攔住手動(dòng)改路由路徑的直訪。Axios請求封裝要統(tǒng)一處理BaseURL、請求頭注入、響應(yīng)狀態(tài)碼分發(fā)做到全項(xiàng)目只維護(hù)一份HTTP邏輯。請求攔截器里從localStorage取Token塞進(jìn)Authorization頭響應(yīng)攔截器里統(tǒng)一處理401跳轉(zhuǎn)登錄、500彈錯(cuò)誤提示。有個(gè)容易忽略的細(xì)節(jié)上傳圖片用的是multipart/form-data格式和普通JSON請求的Content-Type不一樣封裝時(shí)要單獨(dú)留出上傳方法別讓統(tǒng)一攔截器把請求頭搞亂。3.2 Element Plus快速搭建后臺界面Element Plus對管理端開發(fā)效率提升非常明顯。表格用el-table、表單用el-form、彈窗用el-dialog、提示用el-message基本覆蓋了管理端90%的場景。菜品管理頁是最典型的CRUD頁面結(jié)構(gòu)上分成三個(gè)區(qū)域頂部搜索篩選欄、中間表格區(qū)、底部或彈窗表單區(qū)。表格列綁定數(shù)據(jù)字段狀態(tài)列用el-tag組件顯示不同顏色操作列放編輯和刪除按鈕刪除時(shí)二次確認(rèn)彈窗是必須的防止手滑誤刪。新增和編輯共用一個(gè)彈窗表單彈窗打開時(shí)判斷是新增還是編輯模式編輯模式需要把當(dāng)前行數(shù)據(jù)回填到表單提交時(shí)區(qū)分調(diào)create接口還是update接口。這個(gè)“一窗兩用”的設(shè)計(jì)很常見理解了它其他管理頁面基本是一個(gè)套路。用戶端點(diǎn)餐頁面則更注重交互設(shè)計(jì)。左側(cè)是分類導(dǎo)航欄點(diǎn)擊切換右側(cè)菜品列表每個(gè)菜品卡片顯示圖片、名稱、描述、價(jià)格右下角一個(gè)“加入購物車”按鈕。列表數(shù)據(jù)量大的時(shí)候可以加一個(gè)關(guān)鍵詞搜索框做前端本地過濾請求后端搜索接口也是可以的但畢設(shè)場景下前端過濾就夠了體驗(yàn)還更流暢。購物車頁面我用表格形態(tài)展示左側(cè)菜品信息中間數(shù)量增減器右側(cè)小計(jì)金額底部總計(jì)金額和結(jié)算按鈕。數(shù)量變化要實(shí)時(shí)計(jì)算總價(jià)Vue的計(jì)算屬性是最合適的方案——不需要監(jiān)聽每個(gè)變更事件數(shù)據(jù)變了視圖自動(dòng)更新。3.3 狀態(tài)管理與Vuex/Pinia的使用邊界很多同學(xué)對狀態(tài)管理庫的使用邏輯從一開始就是錯(cuò)的把能塞進(jìn)狀態(tài)的數(shù)據(jù)全塞進(jìn)去結(jié)果代碼里到處是store文件引用來引用去數(shù)據(jù)流向變得特別難排查。以點(diǎn)餐系統(tǒng)為例真正需要放進(jìn)全局狀態(tài)的數(shù)據(jù)只有兩個(gè)用戶登錄信息Token和用戶基本資料、購物車數(shù)據(jù)多頁面共享。其他數(shù)據(jù)比如當(dāng)前選中的分類、搜索關(guān)鍵詞、訂單列表都屬于局部狀態(tài)放在組件內(nèi)部管理就好。全局狀態(tài)太多是新手項(xiàng)目變亂的根源一定要克制。Vue3項(xiàng)目推薦Pinia。它的API比Vuex簡潔得多不需要寫mutation這種東西直接定義state、getters、actions就行了。購物車store里定義items數(shù)組actions提供addItem、removeItem、updateCount、clear四個(gè)方法。頁面組件里調(diào)用這些action數(shù)據(jù)自動(dòng)全局同步——首頁加購的菜品切到購物車頁就在列表里了。徹底搞懂“什么數(shù)據(jù)該放store、什么數(shù)據(jù)不該放”之后前端的代碼組織能力會(huì)上一個(gè)臺階。3.4 移動(dòng)端適配要不要做點(diǎn)餐系統(tǒng)的使用場景天然偏向手機(jī)所以移動(dòng)端適配不做說不過去。但畢設(shè)精力有限全手寫響應(yīng)式工作量不小。折中方案是用戶端使用Vant組件庫。Vant是移動(dòng)端Vue組件庫按鈕、彈層、表單、布局全部按移動(dòng)端尺寸設(shè)計(jì)直接引入使用界面天然適配手機(jī)屏幕。管理端保留Element Plus做桌面端。這樣兩套UI庫分工明確用戶端的“點(diǎn)餐感”也強(qiáng)演示時(shí)用瀏覽器開發(fā)者工具切到手機(jī)尺寸看效果視覺沖擊力比桌面網(wǎng)頁好很多。Vant的van-list支持下拉加載更多配合后端分頁接口菜品較多的場景下做無限滾動(dòng)列表體驗(yàn)非常好。這里要記住一個(gè)原則分頁參數(shù)頁碼、每頁條數(shù)由前端傳入后端只負(fù)責(zé)按參數(shù)返回?cái)?shù)據(jù)不要在前端硬編碼“一次性加載全部”。4. 前后端聯(lián)調(diào)、部署與避坑指南4.1 跨域到底是怎么一回事前后端分離開發(fā)最折磨人的問題之一就是跨域。前端跑在localhost:5173后端跑在localhost:8080端口不同瀏覽器就會(huì)攔截跨域請求。原理層面要說清楚瀏覽器的同源策略要求協(xié)議、域名、端口三者一致才能正常發(fā)起Ajax請求。前后端分離環(huán)境下端口必然不一致所以必須解決跨域。解決方式有三種網(wǎng)關(guān)轉(zhuǎn)發(fā)、Nginx反向代理、后端配置CORS。畢設(shè)場景最簡單有效的是后端配置CORS——寫一個(gè)WebMvcConfigurer配置類重寫addCorsMappings方法設(shè)置允許的來源、請求頭、請求方法、是否攜帶憑證即可。允許來源可以寫成前端地址或者通配符但要注意如果前端請求攜帶了自定義請求頭比如Authorization必須把對應(yīng)頭部加進(jìn)允許列表否則瀏覽器會(huì)報(bào)預(yù)檢失敗。聯(lián)調(diào)環(huán)境直接把a(bǔ)llowedOriginPatterns設(shè)為全允許開發(fā)省心上線前再收緊。4.2 聯(lián)調(diào)階段的接口規(guī)范約定前后端分離項(xiàng)目里接口文檔是兩撥人協(xié)作的“契約”。正規(guī)項(xiàng)目用Swagger自動(dòng)生成畢設(shè)項(xiàng)目寫一份簡潔的接口說明文檔也完全夠用關(guān)鍵是把請求路徑、請求方式、請求參數(shù)、返回?cái)?shù)據(jù)結(jié)構(gòu)寫清楚。返回格式強(qiáng)烈建議統(tǒng)一。我用的標(biāo)準(zhǔn)格式是code整數(shù)狀態(tài)碼、message提示信息、data數(shù)據(jù)主體。所有接口成功時(shí)code為200業(yè)務(wù)錯(cuò)誤返回特定業(yè)務(wù)碼比如菜品庫存不足返回50001系統(tǒng)異常返回500。前端Axios響應(yīng)攔截器里統(tǒng)一判斷code成功就返回data給頁面失敗就彈出message頁面代碼不用每個(gè)接口都寫一遍錯(cuò)誤處理。聯(lián)調(diào)階段最常遇到的鬼問題就是字段名對不上。前端List里拿到的字段叫createTime后端JSON里的字段名卻是create_time頁面渲染全是undefined。規(guī)范的做法是后端統(tǒng)一返回駝峰命名SpringBoot默認(rèn)Jackson配置已經(jīng)做了這個(gè)轉(zhuǎn)換如果因?yàn)槟承┨厥馀渲米兞私ㄗh核實(shí)一下序列化配置。4.3 構(gòu)建打包與本地部署演示答辯或者給導(dǎo)師演示時(shí)直接跑npm run dev加后端IDE啟動(dòng)是不太穩(wěn)的——萬一現(xiàn)場網(wǎng)絡(luò)有問題、端口被占、環(huán)境變量缺失就手忙腳亂了。正確姿勢是構(gòu)建出可獨(dú)立運(yùn)行的部署包。前端執(zhí)行npm run build產(chǎn)物在dist目錄。后端執(zhí)行mvn package產(chǎn)物是jar包。部署方案有兩種第一種簡單粗暴把dist目錄下的文件復(fù)制到SpringBoot項(xiàng)目的src/main/resources/static目錄下重新打包這樣jar包自帶前端頁面單機(jī)運(yùn)行只要執(zhí)行java -jar xxx.jar就能訪問系統(tǒng)第二種是把前端靜態(tài)文件扔給Nginx處理API請求反向代理到后端8090端口。畢設(shè)演示用第一種方案就好省去配置Nginx的時(shí)間和現(xiàn)場出問題的概率。后來我知道可以在后端配一個(gè)Controller把未匹配的前端路由轉(zhuǎn)發(fā)到index.html能解決Vue路由history模式刷新404的問題本地演示確實(shí)穩(wěn)。部署環(huán)境注意MySQL也要跟著一起。最穩(wěn)妥的做法是把建表SQL和數(shù)據(jù)初始化腳本整理成單獨(dú)的.sql文件新環(huán)境一鍵導(dǎo)入避免手敲數(shù)據(jù)。4.4 答辯現(xiàn)場的前后端分離講解技巧答辯時(shí)講前后端分離重點(diǎn)不是背概念而是用自己項(xiàng)目的實(shí)際內(nèi)容說明白“分離”的價(jià)值。我當(dāng)時(shí)是這么講的前端負(fù)責(zé)渲染和交互后端負(fù)責(zé)業(yè)務(wù)邏輯和數(shù)據(jù)安全兩者通過標(biāo)準(zhǔn)HTTP接口通信。舉一個(gè)具體的例子購物車結(jié)算時(shí)前端只是把購物車的菜品列表發(fā)給后端后端要校驗(yàn)菜品是否存在、價(jià)格是否正確、庫存是否夠——規(guī)則的權(quán)力在后端前端沒有決策權(quán)。數(shù)據(jù)流可以從用戶點(diǎn)擊“提交訂單”按鈕開始前端調(diào)用后端下單接口后端校驗(yàn)、落庫、返回訂單編號前端跳轉(zhuǎn)支付模擬頁支付成功后前端輪詢或直接跳轉(zhuǎn)到訂單列表頁看到新狀態(tài)。理清這一條主鏈路整個(gè)項(xiàng)目的邏輯就講透了。再強(qiáng)調(diào)一個(gè)容易被問倒但其實(shí)是送分題的點(diǎn)為什么不用Session而用JWT。把“服務(wù)端無狀態(tài)、多端復(fù)用、解耦集群會(huì)話”這幾個(gè)核心優(yōu)勢表達(dá)清楚就夠了。如果被追問JWT的缺點(diǎn)就承認(rèn)它無法服務(wù)端主動(dòng)失效、密鑰需要妥善保管這些不是致命傷但對新手的誠實(shí)度是加分項(xiàng)。5. 擴(kuò)展方向與實(shí)戰(zhàn)經(jīng)驗(yàn)總結(jié)5.1 三個(gè)值得做的擴(kuò)展點(diǎn)畢設(shè)做到能用只是第一步如果想要更好的成績或者為以后面試攢項(xiàng)目亮點(diǎn)下面三個(gè)方向值得考慮。接入真實(shí)支付雖然復(fù)雜但可以作為一個(gè)“模擬支付”模塊來設(shè)計(jì)。前端點(diǎn)擊支付時(shí)彈出一個(gè)確認(rèn)框點(diǎn)擊確認(rèn)后調(diào)用后端支付接口后端直接修改訂單狀態(tài)為已支付。整個(gè)過程中把支付網(wǎng)關(guān)的對接流程畫進(jìn)論文的時(shí)序圖里說明真實(shí)場景是第三方支付平臺回調(diào)通知后修改訂單狀態(tài)這就能體現(xiàn)出你對“異步回調(diào)”的理解。這種設(shè)計(jì)論文里價(jià)值很高。引入Redis做緩存也值得寫進(jìn)加分項(xiàng)。菜品列表是讀多寫少的典型場景把高頻訪問的菜品數(shù)據(jù)緩存到Redis設(shè)置合理的過期時(shí)間數(shù)據(jù)變更時(shí)手動(dòng)清除相關(guān)緩存。如果答辯時(shí)能說清楚緩存穿透和緩存雪崩的基本概念哪怕項(xiàng)目沒有全部實(shí)現(xiàn)也是一段漂亮的拓展內(nèi)容。用戶端加強(qiáng)餐品評價(jià)功能包括評分、文字評價(jià)、圖片上傳再配合一個(gè)按評分排序的接口就是一個(gè)完整的功能閉環(huán)。訂單完成后才能評價(jià)評分?jǐn)?shù)據(jù)同步展示在菜品詳情頁邏輯上不復(fù)雜但業(yè)務(wù)完整度提升很大。5.2 開發(fā)時(shí)間投入與節(jié)奏建議給正在做類似項(xiàng)目的同學(xué)一個(gè)時(shí)間參考數(shù)據(jù)庫設(shè)計(jì)兩天、后端接口十五天、前端頁面十天、聯(lián)調(diào)測試五天。這是對于每天三到五個(gè)小時(shí)投入的估算。數(shù)據(jù)庫表設(shè)計(jì)階段多花點(diǎn)時(shí)間非常值得模型想清楚了后端寫起來就是搬磚模型設(shè)計(jì)的毛病會(huì)一直拖累到項(xiàng)目做完。寫代碼時(shí)要有版本管理意識。哪怕一個(gè)人開發(fā)也建議用Git管理每天提交一次刪掉寫壞了的功能不至于回不了頭畢業(yè)論文里的技術(shù)敘述也更誠實(shí)。日志打印從一開始就做。關(guān)鍵方法入口打印參數(shù)異常打印堆棧。調(diào)試時(shí)省下的時(shí)間遠(yuǎn)超寫日志的時(shí)間成本。很多同學(xué)出問題找不到原因就是因?yàn)槿虥]有任何日志輸出斷點(diǎn)調(diào)試一多又理不清調(diào)用鏈。5.3 從畢設(shè)到作品集這個(gè)項(xiàng)目做完、論文寫完只是起點(diǎn)。把它整理進(jìn)簡歷的時(shí)候記得寫清楚項(xiàng)目亮點(diǎn)——前后端分離架構(gòu)、JWT認(rèn)證、事務(wù)管理、樂觀鎖、統(tǒng)一接口規(guī)范、分模塊開發(fā)。面試問到項(xiàng)目時(shí)把自己遇到的真實(shí)問題隱藏最深的坑往往是圖片上傳返回404、Token過期不跳轉(zhuǎn)、并發(fā)下單庫存超賣和解決過程講出來比背一堆概念有用得多。分享一個(gè)很實(shí)在的心得代碼能力靠寫但也靠改。一遍寫通的項(xiàng)目其實(shí)收獲有限把沒做好的模塊重新梳理、擴(kuò)展、美化才是把畢設(shè)價(jià)值榨干的正確方式。祝你們能順利完成有問題評論區(qū)聊。