站畢設(shè)項目實戰(zhàn):從數(shù)據(jù)庫設(shè)計到部署上線全解析)
SpringBootVue做手機銷售網(wǎng)站屬于Java Web畢設(shè)里非常經(jīng)典的前后端分離項目。說句實在話這類項目在GitHub和碼云上一抓一大把但大多數(shù)學生下載下來之后根本跑不起來——不是缺這個配置就是少那個依賴更別提把數(shù)據(jù)庫腳本導進去之后一堆外鍵報錯。我前前后后幫人排查過幾十個這種項目今天就把一個能真正跑通的完整方案拆開揉碎了講清楚。這個項目涉及的核心內(nèi)容有這么幾塊SpringBoot后端接口、Vue前端頁面、MySQL數(shù)據(jù)庫腳本、接口文檔。對于做畢設(shè)的學生來說你需要的不只是一個能點來點去的Demo而是一套能講清楚為什么這么設(shè)計的完整邏輯。我這篇文章就按照實際開發(fā)順序來拆解包含技術(shù)選型、數(shù)據(jù)庫設(shè)計、接口實現(xiàn)、前后端聯(lián)調(diào)、部署上線以及那些最容易讓你在答辯時翻車的隱藏坑。1. 先搞清楚手機銷售網(wǎng)站到底需要哪些功能模塊很多同學拿到題目就懵了手機銷售網(wǎng)站那不就是個商品列表加購物車嗎真這么做下去到答辯的時候你會發(fā)現(xiàn)根本沒東西可講。一個合格的手機銷售網(wǎng)站在畢設(shè)層面至少要覆蓋前臺展示和后臺管理兩個大方向功能拆解下來大概是這樣的。前臺用戶端主要面向普通消費者。用戶注冊登錄是基礎(chǔ)然后就是手機商品的瀏覽和篩選。這里有個關(guān)鍵點手機和普通商品不一樣它有品牌、操作系統(tǒng)Android還是iOS、運行內(nèi)存、存儲容量、屏幕尺寸、電池容量這些細分屬性。所以搜索篩選功能不能只做一個簡單的關(guān)鍵字匹配而是要支持多維度的組合篩選比如同時按華為和8GB運存來過濾。購物車和訂單系統(tǒng)是交易閉環(huán)的核心。用戶把手機加入購物車之后要能修改數(shù)量、刪除商品、計算總價提交訂單時還得填寫收貨地址。這里牽扯出一個畢設(shè)里很關(guān)鍵的考察點庫存扣減。很多同學用的是先下單再減庫存甚至干脆不處理這在高并發(fā)場景下會有超賣風險。畢設(shè)做單體應用可以用數(shù)據(jù)庫的行級鎖或者樂觀鎖來處理但關(guān)鍵是你得能把這個邏輯講清楚。后臺管理端則是給管理員用的。商品的增刪改查是必須的包括手機的名稱、價格、庫存、圖片、詳細介紹這些字段。另外品牌管理和分類管理可以單獨做一張表方便前臺按品牌篩選。訂單管理要能查看所有訂單列表、修改訂單狀態(tài)待付款、待發(fā)貨、已發(fā)貨、已完成、已取消。用戶管理一般就是查看用戶列表和啟用禁用賬號。這里我建議加一個數(shù)據(jù)可視化看板雖然會增加工作量但這是答辯時的加分項。用ECharts做幾個圖表放在首頁——比如按月統(tǒng)計銷售額的折線圖、各品牌手機銷量占比的餅圖、庫存不足預警的列表。這能直接證明你對業(yè)務(wù)數(shù)據(jù)的理解而且實現(xiàn)起來也不復雜就是查幾張表做聚合統(tǒng)計。需要注意的是功能模塊的劃分最好在文檔和數(shù)據(jù)庫設(shè)計階段就定下來不要邊寫代碼邊加功能。我見過太多同學后面改表結(jié)構(gòu)改到崩潰因為前端頁面、后端接口、數(shù)據(jù)庫字段三處是關(guān)聯(lián)的牽一發(fā)而動全身。2. 技術(shù)選型不是越新越好關(guān)鍵看穩(wěn)定和匹配先說說后端。SpringBoot的版本這里有個容易踩的坑。很多學生下載項目的時候習慣去Maven倉庫拉最新版比如SpringBoot 3.x結(jié)果發(fā)現(xiàn)JDK版本要17以上之前寫的代碼里很多寫法要調(diào)整還有一些老版本的依賴不兼容直接原地爆炸。畢設(shè)項目我強烈建議用SpringBoot 2.7.x系列。這個版本非常成熟網(wǎng)上資料最多遇到問題搜一下基本都能找到解決方案。它默認兼容JDK 8而大多數(shù)學校機房和企業(yè)里用的還是JDK 8你在答辯演示的時候環(huán)境不會出問題。如果已經(jīng)下載的Demo是SpringBoot 3.x優(yōu)先考慮整體替換回2.7.x而不是去適配新版本。持久層框架推薦MyBatis-Plus而不是原生MyBatis。我們做畢設(shè)主要是把精力放在業(yè)務(wù)邏輯上MyBatis-Plus的通用Mapper能自動幫我們生成單表的增刪改查SQL避免寫大量重復的XML文件。它提供的分頁插件也比較好用Web層配合前端的分頁組件代碼量少一大截。前端這塊Vue版本選擇也講究。Vue 2和Element UI的搭配是最成熟穩(wěn)妥的組件全坑少網(wǎng)上的案例也多。Vue 3搭配Element Plus也可以API更現(xiàn)代但如果你對Vue還不熟建議用Vue 2。另外前端構(gòu)建工具、狀態(tài)管理這些如果時間緊張可以選輕量方案用Vuex組件通信傳參處理簡單需求就夠了。前端UI框架Element UI算是最常用的。表格、表單、彈窗、分頁這些核心組件都有而且美觀度在后臺管理系統(tǒng)中足夠用了。如果是自己做前臺用戶界面手機銷售這類面向消費者的頁面Element UI風格會顯得稍微偏后臺但畢設(shè)階段完全可以接受。你可以在確認功能完整的前提下想著把視覺優(yōu)化一下比如設(shè)計和交互做得更有質(zhì)感一些。最后說數(shù)據(jù)庫。MySQL 5.7或者8.0都可以如果你是學習用途建議8.0反正市面上絕大多數(shù)項目都支持。有一點要提醒MySQL 8.0默認的認證插件是caching_sha2_password有些舊版本的數(shù)據(jù)庫連接工具連接不上但我們在SpringBoot里用的mysql-connector-java驅(qū)動8.0以上的版本已經(jīng)兼容了所以問題不大。連接數(shù)據(jù)庫的時候注意時區(qū)配置在JDBC連接地址后面加上serverTimezoneAsia/Shanghai不然會有8小時時差問題。3. 數(shù)據(jù)庫表設(shè)計直接決定開發(fā)效率和答辯分數(shù)手機銷售網(wǎng)站的數(shù)據(jù)庫表說復雜也復雜說簡單也簡單但有幾個設(shè)計原則你最好遵守這決定了后面寫代碼的時候是順手還是別扭。核心表就這些用戶表sys_user、手機商品表phone、品牌表brand、購物車表cart、訂單表orders、訂單明細表order_item、輪播圖表banner、收貨地址表address。先看用戶表核心字段是用戶名、密碼、昵稱、手機號、頭像、角色標識。角色這里需要多說一句雖然我們不搞復雜的權(quán)限框架但管理員和普通用戶肯定要區(qū)分。可以用role字段值為1表示管理員值為0表示普通用戶。這樣前端登錄后可以根據(jù)角色決定顯示哪些菜單后端也可以在攔截器里根據(jù)角色做接口訪問限制。還有密碼存儲千萬不要明文存放。比較簡單的做法是用MD5加鹽或者用Spring Security的BCryptPasswordEncoder。如果項目里沒接Security自己寫MD5加鹽工具類也行但答辯的時候要能說出這樣做的理由。手機商品表是業(yè)務(wù)的重心。字段包括手機名稱、品牌ID、價格、原價、庫存、銷量、主圖URL、詳情圖URL列表、操作系統(tǒng)、運行內(nèi)存、存儲容量、屏幕尺寸、電池容量、處理器型號、上市時間、上下架狀態(tài)。注意品牌ID是外鍵關(guān)聯(lián)品牌表的這樣你按品牌篩選的時候直接查這個字段就行。價格字段推薦用DECIMAL(10, 2)類型不要用FLOAT或DOUBLE不然會出現(xiàn)浮點數(shù)精度問題。訂單表要設(shè)計好狀態(tài)字段。用一個status字段存儲訂單狀態(tài)后臺管理系統(tǒng)里常見的狀態(tài)機是0待付款1待發(fā)貨2待收貨3已完成4已取消。前端根據(jù)狀態(tài)碼顯示對應的按鈕。訂單表和訂單明細表是一對多的關(guān)系一個訂單里有多個商品條目。設(shè)計訂單明細表時除了商品名稱和數(shù)量最好把下單那一刻的商品快照價格也存下來因為商品價格后來可能會改歷史訂單要保留下單時的價格。購物車表比較簡單字段是用戶ID、商品ID、商品數(shù)量加上創(chuàng)建和更新時間就行了。一個用戶往購物車添加商品時如果這個商品已經(jīng)在購物車里了就直接把數(shù)量加一而不是新增一條記錄。輪播圖表主要記錄圖片URL、跳轉(zhuǎn)鏈接、排序權(quán)重前臺首頁展示時按權(quán)重排序。還有一個常見問題需要提醒到底要不要設(shè)置外鍵約束。很多教程項目為了演示方便都加外鍵但實際開發(fā)中大型項目基本都取消物理外鍵只在邏輯上保持關(guān)聯(lián)。畢設(shè)的話建表腳本里保留外鍵是可以的答辯時說是為了數(shù)據(jù)一致性但如果你應用層代碼寫得不好很容易因為外鍵約束導致刪除操作失敗。穩(wěn)妥的方案是建議你放棄物理外鍵在SQL層面通過索引和關(guān)聯(lián)查詢來保證邏輯正確。MySQL執(zhí)行腳本時記得把DROP TABLE IF EXISTS放在每個建表語句前面這樣腳本重復執(zhí)行不會報錯。4. 后端接口不是寫完就行你要懂這幾個核心設(shè)計接口設(shè)計這塊我不想把所有接口名單列一遍那沒意義。我只講幾個最容易出問題、也最能在答辯時體現(xiàn)出你水平的地方。先說接口規(guī)范。既然是前后端分離統(tǒng)一返回格式是必須的。建議定義一個Result類包含code、message、data三個字段。接口成功時code為200失敗時code為500未登錄時code為401無權(quán)限時code為403。前端拿到響應后只要判斷code是否為200為200就正常渲染數(shù)據(jù)否則彈出message提示。這個規(guī)范從始至終要保持一致否則前后端聯(lián)調(diào)的時候會非常痛苦。用戶登錄鑒權(quán)是重點。畢設(shè)項目可以做基于Token的認證簡單方案是登錄成功后生成一個UUID作為Token存到Redis里設(shè)置過期時間返回給前端。前端每次請求都在Header里帶上token字段后端寫一個攔截器在業(yè)務(wù)代碼執(zhí)行前校驗Token校驗通過就放行不通過就返回401。這么做的好處是能夠橫向擴展Session存在服務(wù)器內(nèi)存里的話會有很多麻煩。當然如果你不想引入Redis用JWT也可以把用戶信息加密放到Token里后端用密鑰解密驗證。商品列表接口的設(shè)計要講究一點。手機銷售網(wǎng)站的前臺頁面一般有兩種展示模式一種是搜索加分類篩選另一種是上下拉無限加載。接口其實可以統(tǒng)一成一個通過請求參數(shù)來控制。建議參數(shù)有page頁碼、limit每頁條數(shù)、keyword關(guān)鍵字搜索、brandId品牌篩選、osType操作系統(tǒng)篩選、minPrice和maxPrice價格區(qū)間、sortBy排序字段可以是價格、銷量、上架時間。后端用MyBatis-Plus的分頁插件處理條件構(gòu)造器動態(tài)拼接SQL條件。這個接口寫明白之后前臺的搜索、篩選功能基本就全通了。訂單提交這塊一定要處理事務(wù)。一個完整的下單流程要往訂單表插記錄往訂單明細表批量插記錄要扣減商品庫存要清空購物車里對應的商品。任何一步失敗那么整體的操作就應該回滾這叫要么全部成功要么全部失敗。在SpringBoot里只需要在Service層方法上加Transactional注解就行。還有一個小問題下單時要鎖定庫存減少并發(fā)超賣可以在事務(wù)里對商品行加SELECT ... FOR UPDATE鎖前提是事務(wù)里要包含查詢庫存和更新庫存兩步驟。支付功能要看你的時間預算。如果只是想順利畢業(yè)做一個模擬支付接口就夠了。用戶在付款頁面點確認支付后端直接把訂單狀態(tài)從待付款改成待發(fā)貨在前端提示支付成功。如果你想做得精致點可以在訂單表加一個支付時間字段模擬一下回調(diào)邏輯。千萬不要為了追求真實支付功能去對接支付寶、微信支付的沙箱環(huán)境那會占用你大量時間而且答辯考察的重點也不在支付對接上。這里分享一個我?guī)蛯W生改代碼時常見的低級錯誤很多同學在寫查詢列表接口時沒有處理參數(shù)為空的情況。比如brandId沒傳你可以對條件構(gòu)造器的條件進行非空判斷讓它加到查詢條件里去。MyBatis-Plus條件構(gòu)造器里用StringUtils.hasText()或者判斷對象不為空后再eq關(guān)聯(lián)。5. 前后端聯(lián)調(diào)時那些讓你懷疑人生的細節(jié)前后端分離的項目聯(lián)調(diào)階段是最折磨人的。前端在本地跑dev服務(wù)器后端跑在8080端口跨域問題第一個跳出來。解決跨域有幾種辦法推薦用SpringBoot的全局CORS配置。寫一個配置類實現(xiàn)WebMvcConfigurer接口重寫addCorsMappings方法設(shè)置允許的跨域來源、請求頭和方法。要注意的是如果前端請求帶了Token之類自定義HeaderallowedHeaders里要寫上。設(shè)置SpringBoot應用啟動的端口和上下文路徑需要在前端代理配置文件里同步改vue.config.js里配置devServer的代理轉(zhuǎn)發(fā)這樣前端請求/api開頭的地址就會被代理到后端的localhost:8080/api上。前后端接口字段對不上也是聯(lián)調(diào)時的一大坑。前端要的是createTime你后端返回的卻是create_time。這個問題在MyBatis里尤其容易出現(xiàn)。使用MyBatis-Plus時全局配置里開啟駝峰命名映射那么數(shù)據(jù)庫的create_time字段就能自動映射為實體的createTime屬性。前端拿到的是規(guī)范的駝峰字段就不會對不上了。調(diào)試接口時我推薦兩個工具。一個是Postman后端自己測接口的時候用另一個是瀏覽器的開發(fā)者工具Network面板前端聯(lián)調(diào)時看請求和響應數(shù)據(jù)。學會看請求的URL、Header、Request Payload和響應體大部分接口問題能定位到原因。分頁這塊在前后端聯(lián)調(diào)時也容易出差錯。前端組件傳的pageNum和pageSize后端接口的參數(shù)名必須一致才能接收到。干脆統(tǒng)一一下前端傳page和limit后端就按page和limit來接收。返回的數(shù)據(jù)結(jié)構(gòu)也要約定好建議是{records: [...], total: 100, current: 1, size: 10}前端拿到records渲染列表拿到total算總頁數(shù)。6. 我的建議從下載源碼到成功跑通的完整步驟如果你手里已經(jīng)有一套SpringBootVue的手機銷售網(wǎng)站源碼但就是跑不起來我建議你按順序做不要亂試。第一步檢查JDK版本。項目和你的本地環(huán)境版本匹配否則編譯報一堆奇怪的錯誤。使用Maven的項目導入IDE后更新一下Maven配置把依賴下載完整。第二步配置數(shù)據(jù)庫。打開application.yml或properties文件檢查數(shù)據(jù)源配置。確認MySQL的賬號密碼、端口號對不對。然后用Navicat或命令行執(zhí)行SQL腳本執(zhí)行完確認核心表已經(jīng)創(chuàng)建出來了。第三步改Redis配置。如果項目用了Redis確認本地裝了Redis服務(wù)啟動了。SpringBoot連接Redis的配置在配置文件里默認是localhost:6379密碼為空。如果你本地沒裝Redis而項目里又必須用可以臨時修改代碼把緩存相關(guān)功能去掉但不建議這么做因為會牽連登錄鑒權(quán)邏輯。第四步啟動SpringBoot后端。查看控制臺有沒有報錯信息是否出現(xiàn)Started Application in x.xxx seconds說明啟動成功。此時打開瀏覽器訪問localhost:8080效果看情況如果接口路徑配置合理可以測試接口。第五步啟動Vue前端。進入前端目錄執(zhí)行npm install安裝依賴這個過程可能比較久耐心等待。安裝完成后再執(zhí)行npm run serve。這里有個比較常見的坑是npm install過程中報node-sass安裝失敗。新版項目一般用dart-sass問題不大。如果你遇到的是node-sass上網(wǎng)搜一下對應版本的兼容性或者讓Node版本降級。第六步登錄驗證。前端啟動后打開瀏覽器看到登錄頁就對了。用管理員的賬號密碼登錄進去看看能不能打開后臺管理頁面商品管理能否正常增刪改查數(shù)據(jù)能渲染出來就說明整個鏈路是通的。7. 部署上線的正確姿勢和那些隱藏的系統(tǒng)配置很多學校畢設(shè)要求最后要能演示本地跑通可能還不夠有的老師會要求部署到服務(wù)器上。這里介紹一個最穩(wěn)妥、最省事的方式用寶塔面板部署。買一臺云服務(wù)器裝好寶塔面板之后我們需要做這些事安裝MySQL和Redis如果項目用了安裝Nginx安裝JDK和Maven。然后借助寶塔面板上傳項目代碼或者直接在服務(wù)器上用Git拉取代碼。后端的部署使用Maven打包成可執(zhí)行的JAR文件。在項目根目錄執(zhí)行mvn clean package -DskipTests它會在target目錄下生成一個JAR包。在寶塔的網(wǎng)站管理里添加一個Java項目上傳JAR包把啟動命令配好。啟動命令里也可以指定端口或者直接用配置文件里的server.port。后端部署成功之后服務(wù)器的防火墻或安全組要把對應的端口放行否則外部訪問不到。前端的部署需要先構(gòu)建靜態(tài)文件。在Vue項目目錄執(zhí)行npm run build生成dist目錄。把dist目錄里的文件上傳到Nginx的站點根目錄。然后在Nginx的配置里設(shè)置反向代理當用戶訪問/api路徑時將請求轉(zhuǎn)發(fā)到后端服務(wù)器的地址。記住前端部署在80端口后端跑在8080如果不配置反向代理前端頁面里所有請求都會404但這不影響本地的8080端口訪問所以本地與部署是有差異的。數(shù)據(jù)庫的初始化與遷移生產(chǎn)環(huán)境執(zhí)行一遍SQL腳本腳本是能重復執(zhí)行的但要注意初始化數(shù)據(jù)的冪等性。如果有用到Redis注意給Redis設(shè)置密碼或用訪問控制否則會有安全風險。部署過程確實繁瑣但完成后把訪問地址發(fā)給老師打開就能看到我們的項目這會給老師留下好的印象。很多同學到了答辯前才開始部署結(jié)果手忙腳亂。我建議至少提前一周把服務(wù)器環(huán)境搭好先本地跑通再試著部署一遍時間充裕很多。8. 接口文檔怎么寫才能加分接口文檔這也是畢設(shè)的驗收材料之一很多同學隨便列個表格就交了其實這塊做得好很能加分。我的建議是用Swagger生成在線接口文檔。SpringBoot集成Swagger非常簡單加幾個依賴在啟動類上加EnableOpenApi注解再在Controller的接口上加上Api和ApiOperation注解描述方法和參數(shù)。啟動項目之后訪問localhost:8080/swagger-ui/index.html就能看到清晰的接口列表。每個接口的請求方式、請求參數(shù)、響應結(jié)構(gòu)都能實時調(diào)試。這比手寫一份幾十頁的Word文檔要直觀得多而且改動代碼后文檔會自動同步更新。如果你不想引入Swagger那至少要做一個規(guī)范的Markdown文檔。按照模塊來劃分用戶模塊、商品模塊、購物車模塊、訂單模塊、統(tǒng)計分析模塊。每個接口列清楚URL、請求方式、請求參數(shù)表格名字、類型、是否必填、說明、返回結(jié)果示例。注意寫清楚返回結(jié)果的JSON示例前端同事照著寫代碼。這里分享一個我常見的文檔坑接口文檔里所有參數(shù)都寫了必填但實際后端代碼里有些參數(shù)允許為空。前端嚴格按照文檔傳參時發(fā)現(xiàn)有些篩選條件不需要或者可選容易產(chǎn)生誤解。寫文檔的時候要把每個參數(shù)的校驗邏輯寫清楚比如該參數(shù)可選不傳則查詢?nèi)科放?。這樣前后端溝通起來省很多事。9. 最終檢查和答辯前的準備別在最后一步翻車檢查代碼規(guī)范。Controller層的接口參數(shù)統(tǒng)一用自定義的請求對象去接收不要直接散落一堆RequestParam參數(shù)在方法簽名上。Service層負責業(yè)務(wù)邏輯Controller層盡量只做參數(shù)接收和結(jié)果返回。Repository層承接ORM操作。這樣的三層架構(gòu)答辯的時候畫一張架構(gòu)圖基本就清晰展示了項目的設(shè)計能力。重新梳理項目的核心流程和關(guān)鍵點。答辯前準備一個項目技術(shù)亮點清單重點能講清楚項目采用前后端分離架構(gòu)后端使用SpringBoot數(shù)據(jù)庫采用MySQL登錄鑒權(quán)使用Token機制保證接口安全訂單模塊用事務(wù)機制保證數(shù)據(jù)一致性商品查詢支持多維度篩選和分頁使用數(shù)據(jù)可視化圖表展示銷售數(shù)據(jù)。每一點都能展開講一兩分鐘已經(jīng)非常充足了比背代碼更能展示你的思考。再檢查一遍項目里有沒有硬編碼的問題。數(shù)據(jù)庫連接密碼、Redis密碼不要明文出現(xiàn)在代碼里最好放到配置文件里甚至可以考慮用環(huán)境變量。如果你用的是從網(wǎng)上下載的Demo注意修改包名和項目名不要直接拿別人的包名去答辯老師一查就露餡。最后建議把項目從零搭建過程中踩過的坑整理成一份簡短的開發(fā)日志。這不需要給老師看但答辯時如果被追問項目里遇到過什么問題你就能從自己的經(jīng)歷里挑出來。這種真實經(jīng)驗比背出來的答案更打動老師也是我當年通過答辯的重要心得。手機銷售網(wǎng)站這個題目本身不算難難的是你有沒有把一個完整項目做深做透。技術(shù)不在多在于你能否把每個環(huán)節(jié)的邏輯講清楚。你把這個項目的數(shù)據(jù)庫設(shè)計、接口規(guī)范、權(quán)限方案、事務(wù)一致性這幾個問題搞明白了答辯的時候就能掌握主動權(quán)。