站畢業(yè)設計完整實戰(zhàn)指南)
又到了一年里被畢設題目反復“折磨”的時候最近來問我的學弟學妹里有好幾個拿的都是“SSMVue旅游資源網(wǎng)站”這類題目。實話實說這個題目在計算機類本科畢設里屬于典型的“老牌選手”技術上不算激進但需要做的東西一點也不少。如果能把程序結(jié)構(gòu)和論文思路都打通它既可以當一份完成度很高的畢設也可以在答辯時讓老師清楚地看到你的工程能力。這篇文章我就圍繞“ssmvue旅游資源網(wǎng)站”這個項目從選題邏輯、數(shù)據(jù)庫設計、前后端分工、核心代碼實現(xiàn)、論文寫作和答辯準備幾個維度完整拆一遍。適合正在做同類題目、或者打算拿旅游類網(wǎng)站當畢設項目的人參考哪怕你目前只寫過增刪改查跟著這套思路也能把一個合格的項目搭起來。1. 項目定位與整體設計思路1.1 為什么SSMVue這套組合至今還是畢設的穩(wěn)妥選擇很多學生看到現(xiàn)在到處都是Spring Boot、微服務、前后端分離就會疑惑為什么還要做一個SSM的項目這里有個非常實際的背景不少高校的選題庫和答辯組仍然保留了SSM體系題目寫什么就按什么來這是最穩(wěn)妥的路線。如果提綱上明確寫著“基于SSM框架的旅游資源網(wǎng)站”那你就不要在畢設里私自換成Spring Boot除非指導老師明確表示可以調(diào)整。否則答辯時會面臨“你的題目和實現(xiàn)不一致”的尷尬局面。從技術本身來說SSM不是過時的東西。Spring管對象和事務SpringMVC管請求分發(fā)MyBatis管數(shù)據(jù)庫操作這三者配合能讓一個本科生把“分層思想”講得很清楚。相比Spring Boot那種“自動配置一把梭”的用法SSM反而更能逼迫你去理解Bean、IoC和過濾器這些基礎概念。前端這塊配Vue是加分項。老式畢設喜歡用JSPjQuery做出來的頁面一眼就回到2015年。用Vue做單頁應用配上Element UI或Element Plus頁面的觀感會明顯好于傳統(tǒng)模板渲染。旅游資源這種偏展示型的網(wǎng)站前端體驗恰恰是用戶第一眼關注的東西所以Vue在這里不是炫技而是解決實際問題。1.2 業(yè)務功能邊界把“資源展示”變成可驗收項目很多同學拿到“旅游資源網(wǎng)站”這個題目后第一反應是拼命加功能支付、搶票、線路規(guī)劃、智能推薦……我見過一位同學想做一個完整版“在線旅游電商平臺”結(jié)果寫了三個月連核心流程都沒跑通最后只能熬夜砍功能。正確的思路是先把項目定性成“資源展示輕交互”。游客可以瀏覽景點和旅游線路注冊用戶可以收藏景點、發(fā)表評論管理員可以在后臺管理景點、線路、公告、用戶和評論。這個范圍的拿捏是有講究的有完整的用戶體系注冊、登錄、權限區(qū)分這是每一個答辯老師都會關注的點。有核心業(yè)務實體景點、線路、資訊做的是旅游資源領域的事。有典型的系統(tǒng)行為瀏覽、搜索、詳情、收藏、評論能體現(xiàn)數(shù)據(jù)庫設計和業(yè)務邏輯。有后臺管理端管理員的增刪改查能體現(xiàn)完整的閉環(huán)。把邊界定在這個程度既能在一兩個月內(nèi)做出來又足夠支撐一篇結(jié)構(gòu)完整的論文。支付、地圖、推薦這些可以寫進“未來展望”但不要真花時間去開發(fā)。角色劃分也很清晰我用下表把它結(jié)構(gòu)化角色能做什么對應主體游客瀏覽景點、線路、公告搜索景點前臺公開頁面注冊用戶游客功能 登錄、收藏、評論、個人中心前臺登錄區(qū)管理員用戶管理、景點管理、線路管理、評論管理、公告管理后臺管理端1.3 程序與論文的配合節(jié)奏我后來帶項目時一直強調(diào)一件事不要等程序全部寫完再開始寫論文也不要先把論文編出來再補程序。正確的節(jié)奏是用論文大綱反推程序模塊用程序截圖填充論文。具體操作上我建議先花兩天列出論文的章節(jié)框架摘要寫什么、需求分析分哪幾節(jié)、數(shù)據(jù)庫表畫哪些、系統(tǒng)實現(xiàn)要哪些截圖、測試寫哪些用例。然后按照這個框架去開發(fā)程序每完成一個模塊馬上截圖并寫好功能說明。比如你做完了景點管理就立刻把列表頁截圖、新增頁截圖、修改頁截圖存到一個“論文素材”文件夾里順手寫下這段功能是怎么實現(xiàn)的。這樣到論文階段你不需要回憶“當時那個功能是怎么做的”素材都在手邊寫作速度會快很多而且截圖和程序永遠對得上。很多同學最后要花大量時間返工就是因為程序界面改版后論文里的舊截圖和新代碼對不上答辯時被老師一眼看出來。2. 核心細節(jié)解析與實操要點2.1 數(shù)據(jù)表設計少踩“字段拍腦袋”的坑旅游資源網(wǎng)站的數(shù)據(jù)表不算復雜但設計得規(guī)不規(guī)范答辯老師一眼就能看出來。我通常建議最少建六張表用戶表id、用戶名、密碼、昵稱、手機號、頭像、角色、注冊時間。景點表id、景點名稱、所屬地區(qū)、封面圖片、簡介、詳細內(nèi)容、門票價格、開放時間、創(chuàng)建時間、狀態(tài)。線路表id、線路名稱、出發(fā)地、目的地、天數(shù)、價格、線路圖片、詳情、創(chuàng)建時間。評論表id、用戶id、景點id、評論內(nèi)容、評論時間。收藏表id、用戶id、景點id、創(chuàng)建時間。公告表id、標題、內(nèi)容、發(fā)布時間。這套表里有一個比較常見的坑圖片字段。景點封面圖很可能不止一張但畢設項目沒必要做獨立圖片表。最省事也最穩(wěn)妥的做法是直接在景點表里用一個字符串字段比如cover_image存圖片的相對路徑或完整URL。前端拿到這個字符串直接渲染后面想要多圖用逗號分隔字符也足夠應付。另一個容易出問題的地方是價格字段。做旅游類項目時門票價格、線路價格一定用decimal類型不能圖省事用float或double。很多同學在真實項目中吃過浮點數(shù)計算的虧這里用decimal(10, 2)就能避免價格顯示成99.999999這種奇怪情況。評論表和收藏表都要記得加索引。尤其是收藏表最好對user_id和scenic_id建立唯一索引這樣同一個人重復收藏同一個景點時數(shù)據(jù)庫會直接攔截應用層不用寫一堆判斷邏輯。我當時做的時候后端收藏接口先查一遍是否存在再配合數(shù)據(jù)庫唯一索引雙保險既直觀又防臟數(shù)據(jù)。外鍵策略也值得提前定好。刪除景點時如果該景點下已經(jīng)有評論和收藏直接物理刪除會導致孤兒數(shù)據(jù)。一種做法是刪景點前先刪相關的評論和收藏另一種是給景點表加一個status字段做邏輯刪除。畢設層面我推薦做邏輯刪除答辯時還能解釋“保留歷史數(shù)據(jù)”的業(yè)務含義。2.2 后端分層別把Controller寫成萬能類接手過幾個學生的半成品項目發(fā)現(xiàn)最典型的問題就是Controller里塞滿了業(yè)務代碼查數(shù)據(jù)庫、拼數(shù)據(jù)、寫返回全塞在一個方法里。比如這樣的代碼Controller public class ScenicController { Autowired private JdbcTemplate jdbcTemplate; RequestMapping(/list) ResponseBody public ListMapString, Object list(String keyword) { // 直接在這里寫SQL語句拼條件 String sql select * from t_scenic where name like %keyword%; return jdbcTemplate.queryForList(sql); } }這種寫法功能倒是能做出來但答辯時只要老師追問一句“你的項目怎么分層”就會露出破綻。規(guī)范的SSM項目至少要有Controller、Service、Mapper三層Controller層接收參數(shù)、校驗參數(shù)、調(diào)用Service、返回結(jié)果。Service層處理業(yè)務邏輯比如判斷評論人是否登錄、收藏是否已存在。Mapper層只負責和數(shù)據(jù)庫交互。為了讓前端處理返回值更方便還需要一個統(tǒng)一的返回類型。比如定義Result類包含code、msg、data三個字段。成功就返回new Result(200, 操作成功, data)失敗就返回new Result(500, 操作失敗, null)。前端拿到這個結(jié)構(gòu)體在axios的響應攔截器里統(tǒng)一判斷code彈出提示信息代碼會干凈很多。還有一個小細節(jié)查詢景點列表時全文搜索和分頁要一起做。最簡單的實現(xiàn)是用PageHelper分頁插件在Service層查詢之前調(diào)用PageHelper.startPage(pageNum, pageSize)緊接著執(zhí)行的Mapper查詢就會被自動拼接limit。這個方法用起來很爽但一定要注意startPage和查詢之間不能夾其他數(shù)據(jù)庫操作否則分頁會失效。這個坑我在第4節(jié)還會專門講。2.3 Vue前端的狀態(tài)與路由設計前端部分是整個項目最容易出彩、也最容易翻車的地方。如果你是從零開始又暫時沒有明確要求Vue版本我建議直接用Vue3 Element Plus因為這是現(xiàn)在主流的組合資料多遇到問題也好搜。當然如果學校模板指定的是Vue2 Element UI那也沒必要硬改功能上差異不大。頁面結(jié)構(gòu)上我習慣把前臺和后臺分成兩套路由區(qū)域前臺 / 首頁 /scenic/list 景點列表 /scenic/detail/:id 景點詳情 /route/list 旅游線路 /notice/list 公告列表 /login 登錄 /register 注冊 /user/center 個人中心 后臺 /admin/dashboard 數(shù)據(jù)概況 /admin/scenic 景點管理 /admin/route 線路管理 /admin/user 用戶管理 /admin/comment 評論管理 /admin/notice 公告管理這背后要做三件關鍵的事第一是axios封裝。新建一個request.js配置baseURL指向后端地址請求攔截器從localStorage里取token并放到請求頭響應攔截器統(tǒng)一處理業(yè)務碼。這樣每個頁面調(diào)接口都只需要傳URL和參數(shù)不用重復處理錯誤提示。第二是路由守衛(wèi)。在router/index.js里給后臺路由加上meta: { requiresAuth: true }然后在全局前置守衛(wèi)里判斷如果用戶信息里沒有管理員標記就跳回登錄頁。游客可以訪問的頁面則不需要守衛(wèi)。第三是狀態(tài)管理。Vue3項目用PiniaVue2項目用Vuex把登錄用戶的昵稱、角色、頭像存到store里同時同步到localStorage刷新頁面后從localStorage恢復。很多同學登錄后一刷新就回到未登錄狀態(tài)就是因為只把數(shù)據(jù)存在內(nèi)存里沒有做本地持久化。前臺頁面我建議關注一個體驗點景點列表的卡片布局。每個景點卡展示封面圖、名稱、地區(qū)、價格和一個“去看看”按鈕圖片高度保持一致價格用醒目的顏色標出來整體觀感會比純表格列表好得多。這種頁面細節(jié)花不了太多時間但對答辯印象分提升非常明顯。3. 實操過程與核心環(huán)節(jié)實現(xiàn)3.1 環(huán)境準備與項目骨架搭建先把開發(fā)環(huán)境說清楚推薦組合是JDK 1.8或11MySQL 5.7或8.0Maven 3.6Node.js 16開發(fā)工具IDEA VS Code工作目錄里建議創(chuàng)建前后端兩個文件夾比如tourism-backend和tourism-frontend長期維護起來一眼就懂。后端用Maven管理依賴核心依賴需要這些dependencies !-- Spring核心 -- dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version5.x.x/version /dependency !-- SpringMVC -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version5.x.x/version /dependency !-- MyBatis -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.x/version /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.x.x/version /dependency !-- MySQL驅(qū)動 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.x/version /dependency !-- 數(shù)據(jù)庫連接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.x/version /dependency !-- JSON處理 -- dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId version2.13.x/version /dependency !-- 分頁插件 -- dependency groupIdcom.github.pagehelper/groupId artifactIdpagehelper/artifactId version5.3.x/version /dependency /dependencies這里的版本號我個人建議用穩(wěn)定版本不要一上來就追最新Spring 5.x和MyBatis 3.5.x這種組合已經(jīng)很多項目驗證過了能避免因為版本兼容問題浪費時間。后端配置文件至少有四份jdbc.properties存放數(shù)據(jù)庫連接信息。spring.xml配置包掃描、數(shù)據(jù)源、SqlSessionFactory、事務管理器。spring-mvc.xml配置注解驅(qū)動、靜態(tài)資源放行、視圖解析器如果前后端分離不需要JSP配置。web.xml配置Spring監(jiān)聽器和SpringMVC的DispatcherServlet。前端用Vue CLI創(chuàng)建項目vue create tourism-frontend選擇Vue3預設安裝vue-router、pinia或axios。然后執(zhí)行npm install element-plus element-plus/icons-vueElement Plus在main.js里做完整引入雖然首屏包體積會大一些但畢設項目無所謂開發(fā)效率最重要import { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.css import App from ./App.vue import router from ./router import { createPinia } from pinia const app createApp(App) app.use(ElementPlus) app.use(router) app.use(createPinia()) app.mount(#app)3.2 用戶登錄、角色權限與攔截器登錄接口是畢設項目的“交通樞紐”幾乎所有頁面交互都跟用戶身份掛鉤。我建議登錄做成這樣用戶提交用戶名和密碼Controller接收后調(diào)用ServiceService根據(jù)用戶名查出用戶記錄比對密碼。密碼在數(shù)據(jù)庫里不要存明文注冊時用MD5或BCrypt加密一次登錄時把用戶輸入的密碼做同樣的加密再比對。如果一致生成一個代表登錄狀態(tài)的token返回給前端。token的實現(xiàn)有兩種檔次。最簡單的是Session方案登錄成功把用戶對象放到session里后端攔截器判斷session里有沒有用戶。這種方案代碼少答辯也能講清楚但前后端分離部署時跨域和Session失效問題比較煩人。我推薦用JWT風格的token不一定要引入完整jwt庫模擬一個也可以。登錄成功后后端把用戶id和角色拼成一個帶簽名的字符串返回前端存到localStorage每次請求放請求頭。后端做一個攔截器解析請求頭如果解析失敗就返回401。后端攔截器的核心邏輯public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 如果是跨域預檢請求直接放行 if (OPTIONS.equalsIgnoreCase(request.getMethod())) { return true; } String token request.getHeader(Authorization); if (token null || .equals(token)) { response.setStatus(401); return false; } // 解析token判斷是否有效、是否過期 // 解析出的userId放入request屬性方便Controller使用 return true; } }這個攔截器要注冊到SpringMVC中同時配置放行路徑比如/api/user/login、/api/user/register、/api/scenic/**這些公開接口不需要token而/api/user/center/**、/api/favorite/**則需要登錄。管理員接口比如/api/admin/**還要額外校驗用戶角色是否為1。前端路由守衛(wèi)配合起來也很簡單router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.meta.requiresAuth !token) { next(/login) } else { next() } })3.3 景點檢索、詳情與評論收藏實現(xiàn)景點列表頁是訪問量最高的頁面它的核心是“條件查詢分頁”。哪些條件適合用來篩選最常用的是景點名稱關鍵字、所屬地區(qū)、價格范圍。對應的MyBatis XML我一般這么寫select idselectScenicPage resultMapScenicResultMap SELECT s.id, s.name, s.region, s.cover_image, s.price, s.open_time FROM t_scenic s where if testname ! null and name ! AND s.name LIKE CONCAT(%, #{name}, %) /if if testregion ! null and region ! AND s.region #{region} /if if testminPrice ! null AND s.price gt; #{minPrice} /if if testmaxPrice ! null AND s.price lt; #{maxPrice} /if /where ORDER BY s.create_time DESC /selectService層再配合PageHelperpublic PageInfoScenic getScenicPage(int pageNum, int pageSize, ScenicQuery query) { PageHelper.startPage(pageNum, pageSize); ListScenic list scenicMapper.selectScenicPage(query); return new PageInfo(list); }這樣前端每次只傳pageNum、pageSize和幾個篩選項就能拿到分頁數(shù)據(jù)。景點詳情頁除了顯示景點信息還要顯示評論列表。評論接口按景點id分頁查詢每條評論要帶上發(fā)表人的昵稱和頭像所以SQL要關聯(lián)用戶表。這里用resultMap映射會比resultType更直觀select idselectCommentsByScenicId resultMapCommentResultMap SELECT c.id, c.content, c.create_time, u.nickname, u.avatar FROM t_comment c LEFT JOIN t_user u ON c.user_id u.id WHERE c.scenic_id #{scenicId} ORDER BY c.create_time DESC /select收藏模塊是“用戶與景點”關系的核心實現(xiàn)。接口設計就兩個一個添加收藏一個取消收藏。添加時先查詢是否已收藏如果已收藏就返回提示如果沒有就插入一條記錄。取消收藏直接按userId和scenicId刪除記錄。個人中心里查詢當前用戶的收藏列表時關聯(lián)景點表把景點的基本信息和封面圖帶出來方便做一個“我收藏的景點”卡片列表。后臺管理模塊基本都是增刪改查這里不展開每個接口但有一個思路值得分享后臺列表頁沿用前臺的分頁組件每個管理頁用Element Plus的el-table el-pagination el-dialog組合。彈窗里放表單提交時調(diào)用新增或更新接口成功后刷新表格。這套模式寫熟手之后一張后臺頁面大概一晚上就能做完六張管理頁面也花不了太久。3.4 論文撰寫的章節(jié)組織與查重應對程序做完后論文才是重頭戲。SSMVue旅游資源網(wǎng)站的論文目錄基本是固定的套路我建議按這六章走第一章緒論。寫選題背景和研究意義重點說明“為什么需要旅游資源網(wǎng)站為什么要用JavaVue技術?!弊詈蠓乓粡垏鴥?nèi)外研究現(xiàn)狀的綜述。第二章需求分析。先寫業(yè)務流程再寫功能需求用用例圖展示游客、用戶、管理員各自能做什么。非功能性需求要提性能、易用性、安全性。這一章對應程序里的“功能邊界”寫得越具體后面的系統(tǒng)設計越好寫。第三章系統(tǒng)設計。包括系統(tǒng)總體架構(gòu)圖、功能模塊圖、數(shù)據(jù)庫E-R圖和表結(jié)構(gòu)設計。實際上E-R圖和表結(jié)構(gòu)直接抄自己建的表就行逆向梳理一遍改造成可視化圖形。第四章系統(tǒng)實現(xiàn)。這是論文最占篇幅的一章按功能模塊逐個寫每個模塊放核心代碼片段和運行截圖。注意代碼不用貼全部只貼關鍵方法并配一段文字說明“這是做什么的為什么這么做”。第五章系統(tǒng)測試。寫測試環(huán)境、測試方法然后列測試用例表測試編號、測試項、輸入數(shù)據(jù)、預期結(jié)果、實際結(jié)果。別全寫“通過”針對邊界條件寫一兩個失敗用例反而顯得真實。第六章總結(jié)與展望。總結(jié)做了一個什么系統(tǒng)、用了什么技術、有什么不足后續(xù)可以增加什么功能。關于查重我必須提醒一句參考文獻里的概念介紹千萬不要大段復制教科書原文。寫技術介紹時用自己的話把“Spring是什么、MyBatis是什么”重新表述一遍。尤其要小心網(wǎng)上的博客模板很多畢業(yè)論文模板章節(jié)相似度極高直接照抄會被查重系統(tǒng)標紅。正確做法是定義概念后立刻結(jié)合自己項目里的具體場景說一句比如“在本系統(tǒng)中Spring負責管理Service和Mapper對象的創(chuàng)建和依賴注入”這樣既不容易重復又能體現(xiàn)你對技術的掌握。4. 常見問題與排查技巧實錄4.1 跨域報錯與預檢請求處理前后端分離最常遇到的就是跨域問題?,F(xiàn)象很明確前端控制臺報No Access-Control-Allow-Origin header is present on the requested resource。原因簡單說就是前端跑在http://localhost:8080后端跑在http://localhost:8088瀏覽器認為這不是同一個源。解決辦法一般是在后端加一個跨域過濾器。Component public class CorsFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response (HttpServletResponse) res; response.setHeader(Access-Control-Allow-Origin, http://localhost:8080); response.setHeader(Access-Control-Allow-Credentials, true); response.setHeader(Access-Control-Allow-Methods, GET, POST, PUT, DELETE, OPTIONS); response.setHeader(Access-Control-Allow-Headers, Content-Type, Authorization); chain.doFilter(req, res); } }一個隱藏很深的坑是預檢請求。前端請求帶了Authorization這樣的自定義頭或者請求方法是PUT、DELETE時瀏覽器會先發(fā)一個OPTIONS請求確認服務器是否允許。如果你的后端攔截器把所有OPTIONS請求都攔下來要求登錄跨域就永遠過不了。所以在攔截器的preHandle里一定要放行OPTIONS請求我前面的代碼示例里已經(jīng)寫到了這一步。如果你不想在后端處理跨域也可以在前端利用開發(fā)服務器做代理。在Vue項目的vue.config.js里配置module.exports { devServer: { proxy: { /api: { target: http://localhost:8088, changeOrigin: true } } } }這樣所有/api開頭的請求都轉(zhuǎn)發(fā)到后端瀏覽器看到的是同源地址。但這個方法只對開發(fā)環(huán)境有效正式打包部署后還是要用Nginx或其他方式統(tǒng)一入口。4.2 登錄狀態(tài)反復失效的兩種解決辦法這是我見過學生踩得最多的坑之一表現(xiàn)形式是登錄成功后頁面跳轉(zhuǎn)正常但刷新一下或者點幾個頁面后就提示“未登錄”。如果你用的是Session方案多半問題出在跨域配置沒有帶上Cookie。瀏覽器默認在同源請求時才會攜帶Cookie跨域請求需要后端在響應頭設置Access-Control-Allow-Credentials: true同時前端axios要設置withCredentials: true。但個人建議直接切換成token方案能避開上面這一整攤事。登錄接口返回一個token字符串前端存localStorage每次請求在攔截器里加上service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] token } return config })后端攔截器從請求頭拿到token驗證通過就把用戶信息放到request屬性里后面的Controller直接取。這套方案不受Cookie跨域限制部署到Nginx時也好處理。token還有一個好處是答辯時容易講。你可以說“因為系統(tǒng)采用無狀態(tài)的會話保持方案服務器不需要保存用戶的登錄狀態(tài)減輕了內(nèi)存壓力”這句話翻譯成大白話就是“每個請求都帶著自己的身份證明來過檢”。4.3 MyBatis常見報錯與駝峰映射寫MyBatis遇到報錯是常態(tài)我把高頻問題整理成一張速查表報錯信息本質(zhì)原因解決辦法Invalid bound statement (not found)Mapper接口和XML文件沒有對應上檢查namespace是否等于接口全限定名以及mybatis配置里mapper-locations是否指向xml目錄BindingException: Parameter xxx not found接口方法參數(shù)沒加Param多參數(shù)時必須寫Param(name)查詢結(jié)果全是null列名和實體屬性名不一致開啟mapUnderscoreToCamelCase或?qū)憆esultMapCause: java.sql.SQLSyntaxErrorExceptionSQL語句語法錯誤檢查表名、列名特別是MySQL關鍵字例如表名不要用order、descPageHelper分頁不生效startPage和查詢之間隔了其他數(shù)據(jù)庫操作讓startPage緊貼Mapper查詢執(zhí)行駝峰命名這個問題在SSM項目里特別容易反復出現(xiàn)。Java實體類習慣用createTime數(shù)據(jù)庫列名習慣用create_time如果不在全局配置開啟駝峰映射查出來的createTime就是null。配置方式是在mybatis-config.xml里settings setting namemapUnderscoreToCamelCase valuetrue/ /settings注意只開啟駝峰映射還不夠數(shù)據(jù)庫列名必須真的是create_time這種下劃線格式如果開發(fā)時有人圖省事把列名直接命名為create_time但實體類是create_time那映射出來又會錯所以命名規(guī)范要從建表開始就統(tǒng)一。我個人的習慣是數(shù)據(jù)庫全部用lower_case_with_underscoreJava實體全部用駝峰中間靠MyBatis的映射自動轉(zhuǎn)換。4.4 答辯前最后三天的檢查清單最后說點跟答辯直接相關的實操經(jīng)驗。答辯內(nèi)容、截圖、提問環(huán)節(jié)都有對應的準備技巧建議最后三天按下面的清單過一遍檢查項具體內(nèi)容主流程閉環(huán)從注冊、登錄、瀏覽景點、搜索、收藏、發(fā)表評論到后臺登錄、管理景點全程走一遍任何一步報錯都要當場解決數(shù)據(jù)自洽刪除景點時它下面的評論和收藏怎么處理外鍵約束會不會導致刪除報錯后臺刪除數(shù)據(jù)后前臺會不會出現(xiàn)NullPointerException數(shù)據(jù)庫導出用mysqldump導出一份完整的SQL腳本或者至少在開發(fā)工具里準備好一鍵重建數(shù)據(jù)庫的命令代碼結(jié)構(gòu)可講隨便挑一個Controller你能不看IDE說出它的Service和Mapper分別做了什么嗎論文與截圖一致論文里出現(xiàn)的每一個頁面截圖程序里都必須能找到對應頁面且數(shù)據(jù)最好相同演示環(huán)境穩(wěn)定如果現(xiàn)場沒有網(wǎng)絡數(shù)據(jù)庫和依賴要提前裝好如果用IDEA啟動提前把依賴下載完整避免現(xiàn)場卡在下載還有一個小技巧答辯演示時建議用授課千萬注意不要念代碼。講登錄功能時就說“用戶輸入用戶名密碼后端校驗成功后返回token前端保存到本地之后請求自動攜帶實現(xiàn)會話保持”然后用演示操作補充細節(jié)老師看到的是“論述清晰系統(tǒng)可用”這兩點都滿足分數(shù)一定不會差。這個項目做完之后我個人實際帶項目的體會是畢設最重要的不是技術多炫而是“完整”兩個字。功能鏈路完整文檔和代碼對得上答辯時講得清楚這三點做到就已經(jīng)是一份非常合格的畢業(yè)設計。如果你時間充裕再往里面加一點小創(chuàng)新比如用Redis緩存熱門景點數(shù)據(jù)或者把后臺改造成帶統(tǒng)計圖表的Dashboard就是錦上添花。最后再分享一個小技巧每天開發(fā)結(jié)束后花十分鐘在本地Gitee或GitHub倉庫提交一次代碼。別嫌麻煩那些最后做不下去、程序跑不起來、論文寫不出來的同學大多數(shù)不是能力問題而是改著改著把自己改亂了沒有可以回退的干凈版本。用好了版本控制你的畢設進度就會穩(wěn)很多。