畢設(shè):Spring Boot+MyBatis架構(gòu)與部署答辯全攻略)
簡介一份基于Java的個人博客系統(tǒng)畢業(yè)設(shè)計全套資料包面向計算機(jī)相關(guān)專業(yè)畢業(yè)生與Java Web初學(xué)者可覆蓋選題、開發(fā)、文檔整理與答辯展示的完整需求尤其適合需要從零搭建完整項目的學(xué)習(xí)者。壓縮包大小178.52MB內(nèi)含項目報告、答辯PPT、源代碼、數(shù)據(jù)庫文件與部署教程視頻對應(yīng)需求分析、系統(tǒng)設(shè)計、模塊劃分、接口定義、數(shù)據(jù)表結(jié)構(gòu)及核心編碼實現(xiàn)等核心資料。技術(shù)棧涉及Servlet、JSP、JavaBean、MySQL等后端與數(shù)據(jù)庫技術(shù)以及HTML、CSS、JavaScript、Bootstrap等前端技術(shù)代碼分層清晰便于理解MVC架構(gòu)下的控制層、業(yè)務(wù)層與持久層。目前已有1347人瀏覽學(xué)習(xí)適合作為畢業(yè)設(shè)計參考和Java Web實戰(zhàn)練習(xí)。通過部署視頻可快速完成環(huán)境配置、數(shù)據(jù)庫導(dǎo)入與項目啟動配合答辯PPT和項目報告能直觀呈現(xiàn)系統(tǒng)功能與設(shè)計思路幫助學(xué)習(xí)者少走彎路并提升工程實踐能力尤其對系統(tǒng)測試與部署環(huán)節(jié)可提供直接參照。1. 基于 Java 的個人博客系統(tǒng)畢業(yè)設(shè)計這份資源能幫你省掉哪一段路每年畢設(shè)季問得最多的就是「有沒有一個能直接跑的 Java 項目」這套基于 Java 的個人博客系統(tǒng)畢業(yè)設(shè)計資源包——項目報告 答辯 PPT 源代碼 數(shù)據(jù)庫 部署視頻——就是沖著這個需求來的。它的價值不是讓你什么都不干而是把搭框架、建庫、配環(huán)境的幾周時間壓縮成幾天把精力留給真正要命的事看懂表結(jié)構(gòu)、改出自己講得明白的代碼、練到敢現(xiàn)場演示。適合 Java 方向?qū)W生、想快速交差的初級開發(fā)者以及用博客練 Spring Boot 的入門選手。下面我按「架構(gòu)立住 → 跑起來 → 改得動 → 扛住答辯」的順序把這套資源吃透。2. 把博客畢設(shè)拆開看技術(shù)選型、表結(jié)構(gòu)與文檔框架先立住2.1 為什么是 Spring Boot MyBatis選型理由要能扛住答辯提問拿到源碼第一步不是跑而是先搞清楚它為什么長這樣。常見的 Java 個人博客模板有兩類老一點的是 SSMSpring Spring MVC MyBatis新一點的是 Spring Boot MyBatis 或 Spring Boot JPA?,F(xiàn)在的主流是 Spring Boot 2.x MyBatis理由很實際Spring Boot 內(nèi)嵌 Tomcat、自動配置數(shù)據(jù)源、打 jar 直接跑省去 SSM 那一大堆 XML 配置MyBatis 的 SQL 是自己寫的映射關(guān)系直觀答辯時隨便問一句「你的查詢怎么寫」你能當(dāng)場說出 SQL 而不是解釋一個黑匣子。為什么不用 JPA畢設(shè)規(guī)模下 JPA 的自動建表和懶加載反而是負(fù)擔(dān)尤其是多表關(guān)聯(lián)時 Hibernate 的 N1 查詢問題講不清楚容易翻車。MyBatis 加一個 MyBatis-Plus 的 BaseMapper單表增刪改查幾乎不用寫 SQL代碼量砍一半。模板引擎這邊老項目用 JSP 的不少但現(xiàn)在答辯老師普遍反感 JSP 的部署方式——改一個頁面要重新編譯。我一般建議認(rèn)準(zhǔn) Thymeleaf后端渲染、天然支持 Spring Boot、改頁面只要改模板文件刷新瀏覽器就能看到效果。前后端分離的 Vue REST 方案在工程上是更現(xiàn)代的但對畢設(shè)來說要額外處理跨域、Token、前端打包演示環(huán)境一多踩坑成本翻倍。2.2 五張核心表文章、分類、標(biāo)簽、評論、用戶的關(guān)系一次理清數(shù)據(jù)庫是整個項目里最值得花時間搞懂的部分。一個標(biāo)準(zhǔn)的 Java 個人博客系統(tǒng)表結(jié)構(gòu)逃不出這五張用戶表、文章表、分類表、標(biāo)簽表、評論表加上一張文章和標(biāo)簽的多對多關(guān)聯(lián)表。先建庫再建表。下面是完整可執(zhí)行的 MySQL 腳本我按通常的模板寫法給你拆開。-- 用戶表 CREATE TABLE t_user ( id INT NOT NULL AUTO_INCREMENT COMMENT 用戶ID, username VARCHAR(50) NOT NULL COMMENT 登錄名, password VARCHAR(100) NOT NULL COMMENT 密碼推薦BCrypt密文, nickname VARCHAR(50) DEFAULT NULL COMMENT 顯示昵稱, role TINYINT NOT NULL DEFAULT 1 COMMENT 權(quán)限1管理員 0普通用戶, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 創(chuàng)建時間, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用戶表;-- 文章表 CREATE TABLE t_article ( id INT NOT NULL AUTO_INCREMENT COMMENT 文章ID, title VARCHAR(200) NOT NULL COMMENT 標(biāo)題, summary VARCHAR(500) DEFAULT NULL COMMENT 摘要, content LONGTEXT NOT NULL COMMENT 正文存HTML或Markdown, category_id INT DEFAULT NULL COMMENT 所屬分類ID, user_id INT NOT NULL COMMENT 作者ID, view_count INT NOT NULL DEFAULT 0 COMMENT 瀏覽量, status TINYINT NOT NULL DEFAULT 0 COMMENT 0草稿 1已發(fā)布, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_category (category_id), KEY idx_user (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT文章表;-- 分類表 / 標(biāo)簽表 / 評論表 CREATE TABLE t_category ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_name (name) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT分類表; CREATE TABLE t_tag ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT標(biāo)簽表; CREATE TABLE t_comment ( id INT NOT NULL AUTO_INCREMENT, article_id INT NOT NULL COMMENT 文章ID, user_id INT DEFAULT NULL COMMENT 評論人ID游客為NULL, content VARCHAR(1000) NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_article (article_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT評論表;-- 文章-標(biāo)簽關(guān)聯(lián)表 CREATE TABLE t_article_tag ( article_id INT NOT NULL, tag_id INT NOT NULL, PRIMARY KEY (article_id, tag_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT文章標(biāo)簽關(guān)聯(lián)表;幾個參數(shù)你答辯時最好能主動講出來。第一engineInnoDB支持事務(wù)和行級鎖博客這種讀寫混合的小項目足夠第二charsetutf8mb4而不是utf8因為表情符號也要入庫utf8 存不下 emoji 會直接報錯第三create_time用DEFAULT CURRENT_TIMESTAMP插入時不用手動塞時間第四外鍵我建議不建物理外鍵只建普通索引因為物理外鍵在刪除分類或用戶時會連鎖報錯畢設(shè)階段用邏輯關(guān)聯(lián)在代碼層控制就夠了。第五t_article_tag這種關(guān)聯(lián)表的主鍵用的是聯(lián)合主鍵防止同一篇文章打同一個標(biāo)簽兩遍。2.3 項目報告和答辯 PPT三塊內(nèi)容決定你是 60 分還是 90 分源碼再漂亮報告和 PPT 寫不明白照樣被卡。我的經(jīng)驗是無論模板里原本寫了什么你至少要在這三塊上投入時間。第一塊是需求分析和用例圖別寫「本系統(tǒng)實現(xiàn)了用戶管理」這種廢話要寫「管理員可以發(fā)布、編輯、刪除文章游客可以按分類和標(biāo)簽瀏覽文章并發(fā)表評論」每個角色配兩三個典型流程。第二塊是系統(tǒng)設(shè)計把架構(gòu)圖畫成三層控制層Controller、業(yè)務(wù)層Service、數(shù)據(jù)訪問層Mapper再把 2.2 里的 ER 圖貼上去標(biāo)注主鍵、外鍵和一對多關(guān)系。第三塊是測試結(jié)果除了功能測試用例表強(qiáng)烈建議放兩三個接口測試截圖——用 Postman 調(diào) /article/list、/admin/article/save 這些接口把返回 JSON 貼進(jìn) PPT比十頁功能截圖都有說服力。文檔這塊有個常見翻車點直接從別的畢設(shè)復(fù)制需求分析導(dǎo)致「系統(tǒng)角色」還留著根本沒實現(xiàn)的后臺評論審核功能。答辯老師對項目里沒有的東西問得最狠。我建議對著自己的功能清單一項項核報告里出現(xiàn)的每個功能代碼里必須能找到對應(yīng)入口代碼里有的功能報告里必須有截圖。能做到這個閉環(huán)答辯基本就穩(wěn)了。3. 從源碼到跑起來部署視頻沒拍全的關(guān)鍵步驟與參數(shù)3.1 環(huán)境準(zhǔn)備JDK、Maven、MySQL 的版本匹配關(guān)系部署視頻通常會快進(jìn)這段但環(huán)境不匹配是「跑不起來」的第一大原因這不是玄學(xué)是版本兼容問題。先把三個版本對清楚再動手。java -version mvn -version mysql --version三條命令分別查 JDK、Maven 和 MySQL 的版本。常見的 Java 個人博客模板對應(yīng)的是 JDK 1.8 Maven 3.6 MySQL 5.7 或 8.0。如果你電腦上裝的是 JDK 17直接跑 Spring Boot 2.x 老模板啟動時大概率報UnsupportedClassVersionError或者 CGLIB 相關(guān)錯誤因為新版 JDK 移除了部分反射權(quán)限。兩個處理辦法一是裝一個 JDK 1.8 并在 IDEA 的 Project Structure 里切過去二是把 pom.xml 里的 Spring Boot 版本升到 2.7 以上同時檢查 MyBatis 和 Thymeleaf 的兼容性。我一般傾向第一種成本最低也最貼近模板原作者的運(yùn)行環(huán)境。MySQL 這塊注意一個小細(xì)節(jié)5.7 和 8.0 的驅(qū)動類名不一樣。5.7 用com.mysql.jdbc.Driver8.0 用com.mysql.cj.jdbc.Driver而且 8.0 的連接 URL 必須帶時區(qū)參數(shù)不然報Communications link failure。下面配置章節(jié)我會把標(biāo)準(zhǔn)寫法給出來。如果你用 IDEA直接把源碼目錄當(dāng) Maven 項目導(dǎo)入等依賴下載完成src/main/java下的啟動類會有一個綠色的運(yùn)行按鈕點了就能起——但先別急數(shù)據(jù)庫還沒導(dǎo)。3.2 導(dǎo)入數(shù)據(jù)庫先建庫再導(dǎo)數(shù)據(jù)別跳過 charset資源包里通常會有一個.sql文件可能是blog.sql或database.sql。導(dǎo)入前先做一件事打開看看文件開頭有沒有CREATE DATABASE語句。有的話直接一條命令全導(dǎo)沒有的話先建庫再導(dǎo)。mysql -u root -p -e CREATE DATABASE IF NOT EXISTS blog DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; mysql -u root -p blog blog.sql第一行創(chuàng)建名為 blog 的數(shù)據(jù)庫DEFAULT CHARSET 和 COLLATE 必須顯式指定因為有些 MySQL 服務(wù)器的默認(rèn)字符集是 latin1表即使寫了 utf8mb4建庫這一步兜底錯了后面查中文會亂碼。第二行把 SQL 文件導(dǎo)入到 blog 庫。成功后執(zhí)行mysql -u root -p -e USE blog; SHOW TABLES;能看到 t_user、t_article 這些表就對了。還有一坑有些模板的 SQL 文件里已經(jīng)寫了USE blog;但你本地庫名不叫 blog 叫 blog_system導(dǎo)入時就會把數(shù)據(jù)寫進(jìn)它指定的庫你的配置文件卻連著一個空庫。遇到這種情況要么建一個和文件里同名的庫要么把 SQL 文件里的USE語句注釋掉再導(dǎo)入。導(dǎo)入完了順手查一下 t_user 表有沒有初始賬號數(shù)據(jù)沒有的話自己插入一條管理員賬號密碼先用最簡單的 123456登錄跑通后再改。3.3 application.yml 的五個必調(diào)參數(shù)改錯一個就起不來源碼里在src/main/resources下找到application.yml或application.properties。Spring Boot 2.x 模板基本都用 yml 格式層次比 properties 清楚。下面是按標(biāo)準(zhǔn)寫法給出的最小可用配置server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/blog?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你自己的密碼 driver-class-name: com.mysql.cj.jdbc.Driver thymeleaf: cache: false mybatis-plus: mapper-locations: classpath:mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl五個重點逐一說明。第一server.port改 8080 以外要保證沒被占用。第二URL 里serverTimezoneAsia/Shanghai是 MySQL 8.0 的必填項缺了直接連接失敗。第三characterEncodingutf8配合數(shù)據(jù)庫的 utf8mb4 保證中文不亂碼URL 里的useUnicodetrue也順手留著。第四spring.thymeleaf.cache: false是開發(fā)期福利改 HTML 模板不重啟就能看到效果如果設(shè)成 true你改了首頁死活沒變化就是這個在作怪。第五log-impl配成 StdOutImpl 后每次 SQL 執(zhí)行都會打印到控制臺調(diào)試和答辯排錯都靠它。密碼字段提醒一句本地開發(fā)可以明文但不要把這個配置提交到公開的 GitHub 倉庫源代碼管理里把配置文件的敏感信息替換成環(huán)境變量是基本素質(zhì)。3.4 本地啟動和打包mvn 兩種方式的區(qū)別環(huán)境配好、庫導(dǎo)好、配置改好就可以啟動了。IDEA 里直接點運(yùn)行最省事但更推薦命令行方式因為你以后要寫部署文檔里面所有命令必須是命令行可執(zhí)行的。mvn spring-boot:run這是開發(fā)模式前臺運(yùn)行按 CtrlC 結(jié)束日志實時滾。適合本地調(diào)代碼。mvn clean package -DskipTests java -jar target/blog-0.0.1-SNAPSHOT.jar這是生產(chǎn)模式先跳過測試打包成 jar再java -jar跑起來。打包完你會發(fā)現(xiàn) target 目錄下多了個幾十 MB 的 jar里面帶著內(nèi)嵌 Tomcat扔到任何裝了 JDK 的機(jī)器上都能起這才是部署視頻里常說的「可執(zhí)行文件」。啟動日志里看到Tomcat started on port(s): 8080就成功了瀏覽器訪問http://localhost:8080如果能打開首頁整個鏈路就算跑通。接著做兩件事登錄后臺然后發(fā)一篇測試文章確認(rèn)數(shù)據(jù)庫的增刪改查都是好的。到這一步你已經(jīng)完成了這段畢設(shè)最「虛」但最容易卡住的環(huán)節(jié)。4. 源碼骨架怎么讀、怎么改核心模塊的套路和必調(diào)參數(shù)4.1 登錄與權(quán)限攔截器是最適合畢設(shè)的輕量方案把項目跑起來后就該打開源碼認(rèn)真讀了。我不建議一開始就從 controller 逐行看而是先順著一個請求走完你的登錄請求是怎么進(jìn)到后臺的大多數(shù)個人博客模板用的是攔截器方案而不是 Spring Security因為后者的過濾器鏈、UserDetailsService、權(quán)限配置對畢設(shè)來說太重講不清楚還容易出配置問題。攔截器的實現(xiàn)就是一個類加一段注冊代碼。Component public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object loginUser request.getSession().getAttribute(loginUser); if (loginUser null) { response.sendRedirect(/admin/login); return false; } return true; } }Configuration public class WebConfig implements WebMvcConfigurer { Resource private LoginInterceptor loginInterceptor; Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) .addPathPatterns(/admin/**) .excludePathPatterns(/admin/login, /admin/doLogin, /css/**, /js/**, /images/**); } }這段邏輯的關(guān)鍵在excludePathPatterns登錄接口和靜態(tài)資源必須放行否則樣式全丟、登錄接口也進(jìn)不去。真實模板中這幾個放行路徑經(jīng)常寫漏寫錯表現(xiàn)為「登錄成功了但后臺頁面沒有樣式」八成是/css/**這類沒放行或者 JSP 老模板把靜態(tài)資源放在 webapp 下導(dǎo)致路徑對不上。讀取請求處理流程時順帶把登錄密碼的校驗方式看一眼。好的模板會存 BCrypt 密文答辯時可以主動提一句「密碼不是明文存儲用的 BCrypt 加鹽哈?!埂H绻愕哪0迨敲魑拇婷艽a我建議改掉在 Service 里用BCryptPasswordEncoder的matches方法做校驗改動量不大但這是答辯老師最喜歡的細(xì)節(jié)之一。4.2 文章增刪改查MyBatis-Plus 讓代碼少寫一半文章模塊是個人博客系統(tǒng)的核心你要能講清楚「新增一篇文章從頁面到數(shù)據(jù)庫走過了什么」。常見模板的 Mapper 層寫法是 MyBatis-Plus 風(fēng)格接口長這樣public interface ArticleMapper extends BaseMapperArticle { }你沒看錯空接口就夠了。BaseMapperT內(nèi)置了insert、deleteById、updateById、selectById、selectList等十幾個通用方法單表 CRUD 零 SQL。真正需要寫條件查詢的地方用的是LambdaQueryWrapper比如后臺分頁查文章列表Override public PageArticle pageArticles(int pageNum, int pageSize, String keyword, Long categoryId) { LambdaQueryWrapperArticle wrapper new LambdaQueryWrapper(); wrapper.like(StringUtils.hasText(keyword), Article::getTitle, keyword) .eq(categoryId ! null, Article::getCategoryId, categoryId) .orderByDesc(Article::getCreateTime); return articleMapper.selectPage(new Page(pageNum, pageSize), wrapper); }參數(shù)說明like和eq的第一個參數(shù)是布爾條件為 true 時該條件才生效這樣搜索框沒填關(guān)鍵詞時就自動跳過模糊查詢不需要手動寫三個 if。Article::getTitle是方法引用MyBatis-Plus 靠它解析成數(shù)據(jù)庫字段名避免了硬編碼字符串導(dǎo)致改字段名后 SQL 崩掉。selectPage的返回值Page里帶著records當(dāng)前頁數(shù)據(jù)、total總條數(shù)、current當(dāng)前頁碼、size每頁條數(shù)前端遍歷records分頁組件讀這四個屬性就夠。答辯時老師常追問「分頁怎么實現(xiàn)的」你要能答出兩層應(yīng)用層用 Page 對象傳頁碼和每頁大小MyBatis-Plus 底層自動拼接LIMITMySQL或ROWNUMOracle語句數(shù)據(jù)庫層返回當(dāng)頁數(shù)據(jù)而不是全表。如果你的模板不是 MyBatis-Plus 而是純 MyBatis 的 XML 寫法也沒問題去src/main/resources/mapper/下打開 ArticleMapper.xml你會看到selectPageByCondition這類手寫 SQL那里才是你真正要讀的地方。4.3 前端 Thymeleaf三個必改頁面和它們的屬性套路前端模板頁在src/main/resources/templates/下常見結(jié)構(gòu)是index.html前臺首頁、article.html文章詳情、admin/后臺管理。Thymeleaf 的語法核心就是th:屬性看懂了下面這段首頁列表其他頁面都是變體ul li th:eacharticle, stat : ${page.records} a th:href{/article/{id}(id${article.id})} th:text${article.title}文章標(biāo)題/a span th:text${#dates.format(article.createTime, yyyy-MM-dd)}發(fā)布日期/span em th:text共 ${article.viewCount} 次瀏覽瀏覽量/em /li /ulth:each是循環(huán)page.records對應(yīng) Controller 放進(jìn) Model 的分頁數(shù)據(jù)stat是循環(huán)計數(shù)器可以取stat.index拿序號。th:href的{/article/{id}(id${article.id})}是帶參數(shù)的 URL 寫法比字符串拼接安全自動做 URL 編碼。th:text輸出純文本如果文章正文存的是 HTML詳情頁要用th:utext輸出否則標(biāo)簽會被轉(zhuǎn)義成文字顯示。這是畢設(shè)里出現(xiàn)頻率最高的 bug正文全部變成了帶p標(biāo)簽的源碼就是因為用了th:text。改前端時兩條血淚經(jīng)驗第一頁面里的靜態(tài)資源路徑一律用th:href{/css/style.css}別在 HTML 里手寫/css/style.css否則項目部署到子路徑時全部 404第二后臺表單提交改成 POST 后Controller 要加PostMapping并處理重定向表單驗證出錯時用BindingResult把錯誤信息回顯到頁面。你把這些點改過一遍源碼就算是真正讀懂了。5. 部署與答辯避坑高頻翻車現(xiàn)象、原因與排查方法5.1 數(shù)據(jù)庫連不上時區(qū)、編碼、未建庫三類報錯現(xiàn)象一啟動日志報Communications link failure或The server time zone value ?D1ú±ê×?ê±?? is unrecognized。原因MySQL 8.0 要求連接串顯式指定時區(qū)而配置里沒帶serverTimezone。解決在application.yml的 URL 末尾加上serverTimezoneAsia/Shanghai重啟?,F(xiàn)象二控制臺報Unknown database blog。原因SQL 文件沒導(dǎo)入或者導(dǎo)入時庫名和連接串不一致。解決按 3.2 的命令重新建庫導(dǎo)入然后確認(rèn)配置文件里的庫名和實際庫名一字不差。注意大小寫MySQL 在 Linux 下表名庫名是區(qū)分大小寫的?,F(xiàn)象三中文亂碼頁面上全是???。原因建庫時沒指定utf8mb4或者 JDBC URL 少了characterEncodingutf8。解決把庫、表、連接串三級全部統(tǒng)一成utf8mb4 / utf8改完重新啟動并刷新頁面。這三個問題占了「數(shù)據(jù)庫連不上」九成以上任何一個都可以在答辯現(xiàn)場直接讓你翻車提前用上面的命令自查一遍。5.2 端口被占用和項目起不來現(xiàn)象啟動日志有Port 8080 was already in use。原因之前運(yùn)行的后臺程序沒退干凈或者本地有其他服務(wù)占了 8080。排查命令# Windows 查看占用 8080 的進(jìn)程 netstat -ano | findstr 8080 taskkill /PID 你的進(jìn)程號 /F # macOS / Linux lsof -i :8080 kill -9 你的進(jìn)程號殺掉進(jìn)程后重啟即可。另一個起不來的場景是java -jar啟動后訪問 404原因多半是模板引擎頁面路徑不對——Thymeleaf 默認(rèn)去templates/下找 HTML如果你的頁面放到了static/下Controller 返回的視圖名永遠(yuǎn)找不到控制臺還會打一行Circular view path [index]的警告。解決是確認(rèn)視圖名和templates/下的文件名完全一致區(qū)分大小寫。5.3 打包后資源丟失和靜態(tài) 404現(xiàn)象IDEA 里運(yùn)行一切正常按 3.4 打包成 jar 后再訪問發(fā)現(xiàn) CSS、JS 全部 404。原因打包時資源文件沒被包含進(jìn) jar或者代碼里用了硬編碼路徑。解決打開pom.xml確認(rèn)build段里有resources配置把src/main/resources納入打包然后把頁面里的/css/xx.css全部改成th:href動態(tài)寫法重新mvn clean package。這個坑幾乎人人都踩提前踩完部署演示時就多一分從容。還有個冷門但常發(fā)生的SQL 文件沒被包進(jìn) jar。如果你的初始化 SQL 放在resources/sql/下而 pom 沒包含**/*.sql部署到新機(jī)器上就會「有代碼沒數(shù)據(jù)」。解決是在resources配置里加一條include**/*.sql/include或者干脆把 SQL 文件和 jar 放在一起手動導(dǎo)入。5.4 答辯演示前的四個準(zhǔn)備動作演示翻車往往不是技術(shù)問題是流程問題。第一準(zhǔn)備一個專用演示賬號并確認(rèn)密碼正確不要現(xiàn)場輸密碼手一抖就完蛋。第二預(yù)置演示數(shù)據(jù)至少 5 篇文章、3 個分類、4 個標(biāo)簽、2 條評論別打開后臺發(fā)現(xiàn)是空庫。第三把log-impl的 SQL 日志留著演示時故意操作一次新增文章讓控制臺滾出INSERT INTO語句這是證明「你懂底層」的現(xiàn)場證據(jù)。第四斷網(wǎng)檢查——如果頁面里引用了外部 CDN 的圖標(biāo)或字體答辯教室沒網(wǎng)時頁面會很難看提前把靜態(tài)資源本地化。這四條做完心態(tài)上已經(jīng)贏了七成。5.5 初始賬號找不到模板最容易被忽略的坑現(xiàn)象數(shù)據(jù)庫導(dǎo)入成功但登錄頁面輸什么密碼都報錯。原因SQL 文件里的初始用戶表數(shù)據(jù)有但密碼是加密串你輸?shù)?123456 明文自然匹配不上。解決找到項目里處理登錄的 Service看它用的是 BCrypt、MD5 還是別的算法如果是 BCrypt去在線生成器把 123456 加密后 UPDATE 進(jìn)用戶表如果是 MD5同樣生成密文后更新。這條我建議無論如何都提前做好因為它是「看起來全對但就是進(jìn)不去」的典型黑匣子問題也是我見過導(dǎo)致答辯現(xiàn)場直接斷片的頭號原因。6. 讓畢設(shè)從「能跑」到「能加分」三個進(jìn)階方向與一個驗證方法基礎(chǔ)功能全通后你有余力就可以往加分項上走優(yōu)先級按投入產(chǎn)出比排。第一個是 Markdown 富文本編輯把文章 content 字段存 Markdown 源文展示時用 commonmark-java 庫渲染成 HTML改動只涉及編輯頁和詳情頁兩個地方答辯卻能講出「編輯器層和數(shù)據(jù)展示層分離」的設(shè)計思想。第二個是全文搜索別自己用LIKE %keyword%硬扛數(shù)據(jù)量大了性能斷崖直接給文章表加 MySQL 全文索引用MATCH(title, content) AGAINST(關(guān)鍵詞)查詢一句話就能講清楚「數(shù)據(jù)庫級的全文檢索方案」。第三個是圖片上傳。給后臺加一個圖片上傳接口存儲到本地目錄再把訪問路徑映射成虛擬 URL。這個功能幾乎每個答辯老師都會問「你的圖片存哪」你能答出「服務(wù)器目錄 虛擬映射 數(shù)據(jù)庫存路徑」三層比答「存數(shù)據(jù)庫」高一截。驗證方法用一條命令就能完成。啟動服務(wù)后用 curl 連打三個接口驗證核心鏈路curl -X POST http://localhost:8080/admin/doLogin -d usernameadminpassword123456 curl http://localhost:8080/article/list?pageNum1pageSize5 curl -X POST http://localhost:8080/admin/article/save -d title測試content內(nèi)容categoryId1第一條看登錄是否返回成功第二條看列表是否返回 JSON第三條寫一條測試數(shù)據(jù)后去數(shù)據(jù)庫里查SELECT * FROM t_article ORDER BY id DESC LIMIT 1;確認(rèn)落庫成功。這三步做完你的畢設(shè)從代碼、數(shù)據(jù)到部署就是一條完整的、經(jīng)得起驗證的鏈路。我個人的習(xí)慣是每次改完代碼都跑一遍這三條命令確認(rèn)沒有「改一處崩三處」。希望幫到你。本文還有配套的精品資源點擊獲取