部署全攻略:從環(huán)境配置到答辯演示)
簡介這是一份面向計(jì)算機(jī)專業(yè)畢業(yè)設(shè)計(jì)與課程作業(yè)的智能筆記管理系統(tǒng)項(xiàng)目壓縮包幫助學(xué)習(xí)者從需求分析、界面設(shè)計(jì)到模塊實(shí)現(xiàn)獲得完整參考。壓縮包共54個(gè)文件以35個(gè)vue前端頁面、8個(gè)ts邏輯封裝為主體另含png圖標(biāo)、json配置、html入口、css樣式、gitignore、README說明等整體約203KBsrc目錄下views、router、assets等結(jié)構(gòu)清晰適合VueTypeScript技術(shù)棧的項(xiàng)目實(shí)訓(xùn)與二次開發(fā)。該項(xiàng)目將人工智能理念融入筆記場景覆蓋筆記創(chuàng)建編輯、標(biāo)簽分類、全文搜索及共享協(xié)作并涉及智能推薦、自動(dòng)摘要、語音識(shí)別等擴(kuò)展思路。目前已有163人學(xué)習(xí)下載源碼、依賴鎖定文件與工程配置齊備既可用于快速啟動(dòng)演示也能支撐畢業(yè)設(shè)計(jì)說明書的撰寫與答辯準(zhǔn)備。 收到一個(gè)「智能筆記管理系統(tǒng).zip」大部分人的第一反應(yīng)是解壓、打開、雙擊然后被一串紅色報(bào)錯(cuò)勸退。這類 zip 最常見的真身是一套 Java Web 全棧工程后端提供用戶登錄、筆記增刪改查、分類和搜索接口前端是 Vue 頁面數(shù)據(jù)落在 MySQL。它能解決的是「課程設(shè)計(jì)或畢業(yè)設(shè)計(jì)里如何把這樣一套系統(tǒng)跑起來并講清楚原理」適合正在趕畢設(shè)、做課程作業(yè)或者想快速掌握 SSM/Spring Boot Vue 項(xiàng)目結(jié)構(gòu)的人。下面按我自己落地這類項(xiàng)目的順序走先備環(huán)境再灌數(shù)據(jù)庫跑通前后端最后說高頻故障和能加分的驗(yàn)證思路照著做能少折騰好幾天。2. 環(huán)境準(zhǔn)備JDK8 與 MySQL 的 zip 安裝和三個(gè)常翻車的地方2.1 從「智能筆記管理系統(tǒng).zip」到本地目錄解壓的編碼坑和路徑規(guī)矩拿到 zip 先別急著雙擊先用命令看壓縮包里是什么結(jié)構(gòu)。常見課程作業(yè)工程要么是后端 Maven 工程加前端 Vue 目錄的混合包要么是一個(gè)完整的 Spring Boot 單工程再加一個(gè) database.sql。直接雙擊解壓沒問題但如果你在 Linux 服務(wù)器上干活unzip 對(duì)中文文件名很容易亂碼因?yàn)?Windows 下壓縮時(shí)默認(rèn)用了 GBK 編碼。# 先看壓縮包內(nèi)容再?zèng)Q定怎么解壓 unzip -l xxxx_智能筆記管理系統(tǒng).zip | head -20 # Linux 下用 GBK 編碼解壓避免中文文件名亂碼 unzip -O GBK xxxx_智能筆記管理系統(tǒng).zip -d ~/projects/note-system # 改完代碼后重新打包交付時(shí)排除依賴目錄體積小很多 cd ~/projects zip -r note-system-backup.zip note-system \ -x */node_modules/* -x */target/*第一行只查看文件列表不實(shí)際解壓能確認(rèn)是前后端分離還是單工程結(jié)構(gòu)。第二行的-O GBK參數(shù)在 unzip 5.52 以上版本才有macOS 自帶的 unzip 不支持這個(gè)參數(shù)遇到中文亂碼可以用 7-Zip 或直接用 Windows 資源管理器解壓它默認(rèn)按系統(tǒng)語言處理。第三行是我養(yǎng)成的一個(gè)習(xí)慣每次交付前用zip -r重新打包-x排除node_modules和target這兩目錄加起來動(dòng)輒幾百 MB帶著它們發(fā)給別人完全沒必要而且對(duì)方解壓時(shí)還可能因?yàn)槁窂竭^長報(bào)錯(cuò)。解壓路徑的規(guī)矩比想象中重要。我一般把項(xiàng)目放在D:\projects\note-system這種純英文、無空格的路徑下不會(huì)放到「桌面」或帶中文的目錄。后端讀application.yml里的相對(duì)路徑時(shí)、前端 webpack 打包時(shí)中文路徑和空格偶爾會(huì)觸發(fā)一些詭異問題你說不清是代碼問題還是環(huán)境問題索性一開始就避開。2.2 MySQL 的 zip 安裝初始化、注冊(cè)服務(wù)與 my.ini課程作業(yè)的 MySQL 版本集中在 5.7 和 8.0。官方提供的 zip 包類似 notepad 那種綠色版解壓即用但不是雙擊就能跑必須做四步寫 my.ini、初始化數(shù)據(jù)目錄、注冊(cè) Windows 服務(wù)、改 root 密碼。[mysqld] basedirD:/tools/mysql datadirD:/tools/mysql/data port3306 character-set-serverutf8mb4 collation-serverutf8mb4_general_ci default-storage-engineInnoDB max_connections200 [client] port3306 default-character-setutf8mb4這幾個(gè)參數(shù)里basedir和datadir必須寫成你自己的絕對(duì)路徑。datadir指向的目錄必須不存在或者為空MySQL 初始化時(shí)會(huì)往里面寫系統(tǒng)庫。character-set-serverutf8mb4是中文筆記內(nèi)容不亂碼的第一道保險(xiǎn)很多系統(tǒng)表結(jié)構(gòu)是 utf8但 utf8 在 MySQL 里不是真正的全量 Unicodeemoji 和生僻字會(huì)存不進(jìn)去所以課程作業(yè)我直接建議 utf8mb4。初始化這一步是血淚經(jīng)驗(yàn)重災(zāi)區(qū)。如果執(zhí)行mysqld --initialize會(huì)生成一個(gè)隨機(jī)臨時(shí) root 密碼寫在data目錄下的.err日志里很多同學(xué)找不到這個(gè)文件或者復(fù)制密碼時(shí)把特殊字符看錯(cuò)后面連半天連不上。我一般用--initialize-insecure它生成一個(gè)無密碼的 root省去這層麻煩。# 在 mysql 解壓目錄下執(zhí)行生成 data 目錄 mysqld --initialize-insecure # 注冊(cè) Windows 服務(wù)并啟動(dòng) mysqld --install MySQL --defaults-fileD:/tools/mysql/my.ini net start MySQLmysqld --install后面的MySQL是服務(wù)名可以自己改遇到本機(jī)已經(jīng)裝過 MySQL 服務(wù)時(shí)換個(gè)名字能避免沖突。啟動(dòng)后立刻改密碼ALTER USER rootlocalhost IDENTIFIED BY 123456;MySQL 8.0 里ALTER USER直接IDENTIFIED BY就行別再用老版本的PASSWORD()函數(shù)會(huì)直接報(bào)語法錯(cuò)誤。改完密碼后順手執(zhí)行FLUSH PRIVILEGES;雖然其實(shí)用不到但算是給自己加一層心理安慰。2.3 JDK8 的 zip 壓縮包與 Maven 的取舍這門課的版本玄學(xué)課程作業(yè)工程的 Java 版本幾乎清一色是 JDK8。不是說 JDK17 不行而是這些工程大多基于 Spring Boot 2.x 或更老的 SSM 配置JDK17 下javax包名、反射權(quán)限、CGLIB 代理都可能出兼容問題你花一下午升級(jí)答辯分?jǐn)?shù)不會(huì)因此多一分。JDK8 的 zip 壓縮包下載后解壓到純英文目錄然后配環(huán)境變量。Windows 下在系統(tǒng)屬性里新建JAVA_HOME指向 JDK 解壓目錄再在Path里加%JAVA_HOME%\bin。Linux 下更簡單export JAVA_HOME/opt/jdk1.8.0_xxx export PATH$JAVA_HOME/bin:$PATH java -version輸出里看到1.8.0_xxx就說明生效了。這里有一個(gè)隱藏翻車點(diǎn)電腦里可能已經(jīng)裝了其他版本 JDKPath里后加的路徑優(yōu)先級(jí)可能不夠高導(dǎo)致終端里敲java -version看到的還是舊版本。解決辦法是檢查環(huán)境變量列表里有沒有其他C:\Program Files\Java\jdk-17\bin之類的條目有的話先挪到后面或直接刪掉。Maven 同樣下載 zip 解壓即用不需要安裝向?qū)А5珖鴥?nèi)網(wǎng)絡(luò)環(huán)境下中央倉庫下載依賴經(jīng)??ㄋ肋@是另一個(gè)黑匣子。我習(xí)慣下載壓縮包后先改conf/settings.xml加阿里云鏡像避免mvn clean install拉依賴?yán)揭话雸?bào)Connection timed out。版本選擇上Maven 3.6.x 配合 JDK8 是這門課里最穩(wěn)的組合3.9.x 也能用但沒必要追新。如果你用 IDEA 打開工程后直接點(diǎn)啟動(dòng)IDEA 會(huì)用自己的內(nèi)置 Maven 配置和命令行的settings.xml是兩套注意保持一致否則可能出現(xiàn)「命令行能編譯、IDEA 里全是紅叉」的奇觀。3. 數(shù)據(jù)庫初始化與后端配置筆記表結(jié)構(gòu)和 4 個(gè)必調(diào)參數(shù)3.1 先讀表結(jié)構(gòu)再導(dǎo)入 database.sql解壓后你會(huì)看到一個(gè).sql文件名字多半叫database.sql或note.sql。別直接一把梭導(dǎo)入先打開看一遍建表語句。常見工程至少有三張表用戶表、分類表、筆記表。筆記表是整個(gè)系統(tǒng)的核心字段設(shè)計(jì)大致是這樣表名核心字段用途sys_userid, username, password, nickname, create_time登錄認(rèn)證和用戶信息note_categoryid, user_id, name, sort筆記分類按用戶隔離noteid, user_id, category_id, title, content, tags, is_delete, create_time, update_time筆記主體內(nèi)容我特別關(guān)注兩點(diǎn)一是字符集是不是 utf8mb4二是有沒有is_delete邏輯刪除字段。前者決定中文筆記能不能正常存取后者影響搜索時(shí)要不要加過濾條件。很多工程的搜索接口只寫了WHERE title LIKE ...忘了過濾is_delete 0結(jié)果刪除的筆記還能被搜出來答辯時(shí)被老師一問就露餡。# 命令行導(dǎo)入 SQL 文件 mysql -u root -p123456 --default-character-setutf8mb4 database.sql # 如果要進(jìn)入 mysql 交互環(huán)境手動(dòng)執(zhí)行 mysql -u root -p123456 mysql SET NAMES utf8mb4; mysql SOURCE D:/projects/note-system/database.sql;--default-character-setutf8mb4很關(guān)鍵SQL 文件本身如果是 UTF-8 編碼而客戶端和服務(wù)器字符集不一致導(dǎo)入過程中中文字段值比如預(yù)設(shè)的分類名「工作」「學(xué)習(xí)」就會(huì)變成亂碼。SOURCE是 mysql 交互環(huán)境里導(dǎo)入文件的命令它讀取的是客戶端本地文件注意路徑用正斜杠Windows 下反斜杠會(huì)被當(dāng)成轉(zhuǎn)義字符。導(dǎo)入成功后執(zhí)行SHOW TABLES;確認(rèn)表都存在再看一眼SHOW CREATE TABLE note\G確認(rèn)CHARSETutf8mb4。這一步做到位后面所有「中文亂碼」問題基本都能從源頭上排除一半。3.2 application.yml 里最容易漏的 4 個(gè)參數(shù)后端配置文件的文件名可能是application.yml或application.properties內(nèi)容大同小異。這里是翻車率最高的區(qū)域因?yàn)檎n程作業(yè)的配置經(jīng)常是在某臺(tái)能跑的機(jī)器上拷貝出來的數(shù)據(jù)庫賬號(hào)密碼和你本地對(duì)不上驅(qū)動(dòng)版本也可能不同。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/note_db?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrue username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Drivercom.mysql.cj.jdbc.Driver是 MySQL 8.0 的驅(qū)動(dòng)類5.7 時(shí)代常用com.mysql.jdbc.Driver。如果你本地是 MySQL 8.0配置文件里寫的卻是舊驅(qū)動(dòng)名啟動(dòng)會(huì)直接報(bào)ClassNotFoundException。serverTimezoneAsia/Shanghai不配的話時(shí)間字段會(huì)差 8 個(gè)小時(shí)插入一條筆記列表里顯示的 create_time 是昨天。useSSLfalse是讓驅(qū)動(dòng)別去做 SSL 握手本地開發(fā)完全沒必要加密還能省一點(diǎn)啟動(dòng)時(shí)間。最后一個(gè)allowPublicKeyRetrievaltrue是 MySQL 8.0 的專屬問題。MySQL 8.0 默認(rèn)認(rèn)證插件是caching_sha2_passwordJDBC 驅(qū)動(dòng)第一次連接時(shí)需要獲取服務(wù)器公鑰某些驅(qū)動(dòng)版本默認(rèn)不允許這個(gè)行為于是拋Public Key Retrieval is not allowed。這個(gè)報(bào)錯(cuò)在第 5 章展開說現(xiàn)在先記住URL 里加上它就少一個(gè)坑。密碼字段我加上了引號(hào)因?yàn)?23456是純數(shù)字YAML 解析時(shí)有可能被當(dāng)成數(shù)字類型如果后端框架做了嚴(yán)格類型轉(zhuǎn)換可能出幺蛾子。字符串加引號(hào)是 YAML 的規(guī)范寫法能避免這種邊界情況。3.3 啟動(dòng)后端端口占用和第一次運(yùn)行日志怎么看配置改完就可以啟動(dòng)后端了。如果你用 IDEA直接打開工程找到主類類名一般是NoteApplication或Application右鍵運(yùn)行。想驗(yàn)證命令行能不能跑用 Maven 命令更快mvn clean install -DskipTests java -jar target/note-system-0.0.1-SNAPSHOT.jar第一次跑mvn clean install會(huì)下載大量依賴如果你配置了阿里云鏡像幾分鐘能完成沒配鏡像的話可能卡在某個(gè) jar 的下載上長達(dá)半小時(shí)。-DskipTests是跳過測試代碼編譯后的執(zhí)行課程作業(yè)里若有寫得很糙的單測運(yùn)行時(shí)會(huì)因?yàn)檫B不上數(shù)據(jù)庫直接失敗先跳過是務(wù)實(shí)的選擇。日志看到這一行基本就成功了Tomcat started on port(s): 8080 (http) Started NoteApplication in 12.345 seconds如果端口被占Tomcat 會(huì)報(bào)Port 8080 was already in use。我習(xí)慣直接改配置文件里的server.port: 8081比去殺進(jìn)程快得多反正是課程作業(yè)端口不影響功能。啟動(dòng)成功后先別急著高興打開瀏覽器訪問http://localhost:8080/api/health之類的接口或者直接訪問登錄接口試一下。如果這個(gè)環(huán)節(jié)就 404多半是context-path或server.servlet.context-path配了額外前綴后續(xù)前端聯(lián)調(diào)的時(shí)候要把它拼進(jìn)去。4. 前端工程與接口聯(lián)調(diào)Vue 項(xiàng)目跑通筆記列表的完整鏈路4.1 npm install 與 node_modules 這個(gè)黑匣子前端工程在壓縮包里一般是獨(dú)立目錄里面是 Vue 源碼沒有node_modules。這是正常的任何交付源碼的 zip 都不可能帶依賴目錄。你需要先看package.json確認(rèn) Vue 版本和啟動(dòng)腳本。課程作業(yè)最常見的是 Vue 2 vue-cli 工程scripts里寫的是npm run serve如果是 Vue 3 Vite 工程則是npm run dev。# 先確認(rèn) npm 鏡像源國內(nèi)直接換淘寶鏡像 npm config get registry npm config set registry https://registry.npmmirror.com # 安裝依賴 npm install # 啟動(dòng)開發(fā)服務(wù)器 npm run serve # 或者 npm run devnpm install是前端第一個(gè)黑匣子它輸出幾百行日志但真正重要的只有最后幾行看到added 1234 packages就算成功。中途報(bào)node-gyp或node-sass相關(guān)錯(cuò)誤是最典型的翻車現(xiàn)場node-sass是原生模塊需要針對(duì)當(dāng)前 Node 版本重新編譯課程作業(yè)里常見 Node 14 或 16 配node-sass4.14如果你本機(jī)裝的是 Node 18/20大概率編譯失敗。我的建議是按工程里.nvmrc或 package.json 的engines字段提示安裝對(duì)應(yīng) Node 版本而不是硬著頭皮換sass依賴因?yàn)轫?xiàng)目代碼里寫法可能是scss deep 選擇器換 dart-sass 后語法兼容性又是一堆坑。實(shí)在不想裝多個(gè) Node 版本就用.browserslistrc里給出的版本區(qū)間判斷大方向但我知道這條路不好走。# 裝完依賴還報(bào)錯(cuò)時(shí)先刪干凈重來 rm -rf node_modules package-lock.json npm install這是「后悔藥」把node_modules當(dāng)黑匣子的處理方式不是去查里面的文件而是整個(gè)刪掉重裝。我見過太多人花兩小時(shí)在 node_modules 里翻找某個(gè)包的版本問題最后發(fā)現(xiàn)是安裝過程中斷導(dǎo)致的文件不完整刪掉重裝五分鐘解決。4.2 配置 devServer 代理把跨域問題兜住前后端分離項(xiàng)目最大的聯(lián)調(diào)障礙是跨域前端跑在http://localhost:3000或 8081后端跑在http://localhost:8080端口不同瀏覽器會(huì)攔截前端發(fā)出的 AJAX 請(qǐng)求。課程作業(yè)里最省事的方案不是在后端寫CrossOrigin而是在前端開發(fā)服務(wù)器配代理讓瀏覽器以為所有請(qǐng)求都發(fā)給了同源地址。// vue.config.jsVue 2 vue-cli 工程 module.exports { devServer: { port: 3000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } } }這個(gè)配置的意思是前端所有以/api開頭的請(qǐng)求都會(huì)被開發(fā)服務(wù)器轉(zhuǎn)發(fā)到http://localhost:8080轉(zhuǎn)發(fā)時(shí)把/api前綴去掉。changeOrigin: true是讓轉(zhuǎn)發(fā)請(qǐng)求的Host頭變成目標(biāo)地址的域名很多后端框架會(huì)校驗(yàn)這個(gè)頭不寫可能返回 403。pathRewrite是路徑重寫如果后端接口本身不帶/api就必須有這一步如果后端接口本來就帶/api前綴那pathRewrite留空注釋掉。一個(gè)常見誤用有人在前端的 axios 配置里把baseURL直接寫成http://localhost:8080。這樣確實(shí)能通但屬于繞過了代理而且后端如果配了context-path或?qū)聿渴鸬椒?wù)器換域名代碼里寫死的地址全要改。我一般把 axios 的baseURL設(shè)為/api配合代理這樣瀏覽器控制臺(tái)看到的請(qǐng)求 URL 是干凈的相對(duì)路徑部署時(shí)只要改代理配置不動(dòng)代碼。4.3 從「筆記列表」到「新增筆記」接口聯(lián)調(diào)的最小閉環(huán)配置完代理開始驗(yàn)證接口鏈路。前端工程里一般會(huì)有一個(gè)src/api目錄把請(qǐng)求集中封裝。課程作業(yè)的代碼結(jié)構(gòu)各異但核心思路是把所有接口調(diào)用收斂到一個(gè)模塊里方便統(tǒng)一管理 baseURL 和 token。// src/api/index.js 常見的封裝方式 import axios from axios; const http axios.create({ baseURL: /api, timeout: 10000 }); // 請(qǐng)求攔截器帶上登錄后的 token http.interceptors.request.use(config { const token localStorage.getItem(token); if (token) { config.headers[Authorization] token; } return config; }); export function login(username, password) { return http.post(/user/login, { username, password }); } export function getNoteList(params) { return http.get(/note/list, { params }); } export function createNote(data) { return http.post(/note/save, data); }baseURL: /api配合第 4.2 節(jié)的代理配置是這一套的標(biāo)配。timeout建議設(shè) 10 秒很多時(shí)候接口報(bào)錯(cuò)不是后端掛了而是后端啟動(dòng)太慢前端等 30 秒后瀏覽器超時(shí)你會(huì)以為是自己代碼問題。請(qǐng)求攔截器從localStorage取 token是前后端分離最常見的做法登錄成功后后端返回 token前端存起來后續(xù)每次請(qǐng)求自動(dòng)帶上。聯(lián)調(diào)驗(yàn)證的步驟我按這個(gè)順序走第一打開前端頁面跳過登錄注冊(cè)一個(gè)賬號(hào)。第二在頁面里新建一條筆記標(biāo)題寫「測試筆記」內(nèi)容寫一段中文。第三刷新列表看這條筆記是否出現(xiàn)。第四打開瀏覽器開發(fā)者工具的 Network 面板看請(qǐng)求地址是不是http://localhost:3000/api/note/save狀態(tài)碼是不是 200。如果看到 404檢查代理配置里的路徑和后端接口路徑是否一致看到 500去后端控制臺(tái)看異常堆棧多半是數(shù)據(jù)庫字段映射問題請(qǐng)求根本沒發(fā)出那要檢查攔截器是不是報(bào)錯(cuò)了。這套驗(yàn)證路徑跑通整個(gè)項(xiàng)目的主干功能就算立住了后面填其他頁面都是體力活。5. 避坑專項(xiàng)智能筆記項(xiàng)目跑不起來的 5 個(gè)高頻原因5.1 解壓后沒有 target 和 node_modulesIDEA 里全是紅叉現(xiàn)象解壓后工程目錄里只有源碼pom.xml旁邊沒有target文件夾Vue 目錄里沒有node_modulesIDEA 打開所有類都飄紅。原因交付的 zip 是源碼包依賴不會(huì)打進(jìn)壓縮包。這是正常的不是文件損壞。你從網(wǎng)上下載的「畢設(shè)全套源碼.zip」基本都是這樣。解決后端工程確認(rèn)是 Maven 工程后執(zhí)行mvn clean install -DskipTests讓 Maven 根據(jù)pom.xml下載依賴并編譯前端執(zhí)行npm install。IDEA 里如果還紅右鍵pom.xml選擇「Add as Maven Project」前端目錄則要等待npm install完成后 IDE 自動(dòng)索引。判斷工程是 Maven 還是 Gradle 看根目錄有沒有pom.xml或build.gradle不要憑感覺。5.2 后端啟動(dòng)報(bào) Public Key Retrieval is not allowed現(xiàn)象Spring Boot 啟動(dòng)過程中數(shù)據(jù)源初始化失敗控制臺(tái)報(bào)Public Key Retrieval is not allowed關(guān)鍵字是caching_sha2_password。原因MySQL 8.0 默認(rèn)認(rèn)證插件改為caching_sha2_passwordJDBC 驅(qū)動(dòng)連接時(shí)會(huì)向服務(wù)器請(qǐng)求公鑰做 RSA 加密傳輸密碼。部分驅(qū)動(dòng)版本出于安全考慮默認(rèn)不允許這種公鑰檢索于是直接中斷連接。解決在 JDBC URL 上加allowPublicKeyRetrievaltrueuseSSLfalse完整 URL 見 3.2 節(jié)。如果改完還不行檢查驅(qū)動(dòng)版本是否過舊升級(jí)到mysql-connector-java8.0.20 以上。另一個(gè)治本方案是把 MySQL 用戶的認(rèn)證插件改回老格式ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 123456;但這樣在 MySQL 8.0 里屬于向后兼容新裝環(huán)境建議直接加參數(shù)。5.3 前端頁面能打開接口卻 404 或網(wǎng)絡(luò)錯(cuò)誤現(xiàn)象瀏覽器能顯示登錄頁但點(diǎn)擊登錄后 Network 面板里請(qǐng)求標(biāo)紅要么 404要么ERR_CONNECTION_REFUSED后端控制臺(tái)沒有任何日志。原因axios 的baseURL寫死了后端地址如http://localhost:8080而后端實(shí)際端口或路徑前綴對(duì)不上或者端口對(duì)得上但后端設(shè)置了context-path接口實(shí)際路徑比前端請(qǐng)求的多了個(gè)前綴。ERR_CONNECTION_REFUSED一般是后端沒啟動(dòng)或端口不對(duì)。解決先看 Network 面板里請(qǐng)求的完整 URL跟后端接口實(shí)際路徑做對(duì)比。統(tǒng)一改成第 4.2 節(jié)的代理方案前端baseURL用/api后端保持接口路徑干凈。如果后端必須配context-path把代理配置里的pathRewrite改掉即可但課程作業(yè)我建議后端不要加這個(gè)前綴越簡單越不容易翻車。5.4 保存的筆記中文亂碼搜索「考研」返回空列表現(xiàn)象新建筆記時(shí)輸入中文列表頁顯示成「???」或一堆亂碼搜索中文關(guān)鍵詞永遠(yuǎn)搜不到但搜索英文和數(shù)字正常。原因三個(gè)環(huán)節(jié)任何一個(gè)出問題都會(huì)這樣。第一JDBC URL 沒配characterEncodingutf8連接建立后字符集不對(duì)第二數(shù)據(jù)庫表本身字符集是latin1或utf8中文存進(jìn)去變亂碼第三LIKE查詢條件拼寫錯(cuò)誤比如直接寫LIKE %{keyword}%而 MyBatis 沒做字符串拼接。解決按順序排查。先執(zhí)行SHOW CREATE TABLE note\G確認(rèn)默認(rèn)字符集是utf8mb4不是就ALTER TABLE note CONVERT TO CHARACTER SET utf8mb4;。再檢查 JDBC URL補(bǔ)上characterEncodingutf8。最后看 Mapper XML 里的搜索語句正確寫法是select idsearchNotes resultTypeNote SELECT * FROM note WHERE user_id #{userId} AND is_delete 0 AND (title LIKE CONCAT(%, #{keyword}, %) OR content LIKE CONCAT(%, #{keyword}, %)) /selectCONCAT(%, #{keyword}, %)是 MyBatis 里做模糊搜索的標(biāo)準(zhǔn)寫法。#{}占位符外拼%是無效的因?yàn)?{}會(huì)被編譯成預(yù)編譯語句的參數(shù)%必須作為字符串的一部分傳入用CONCAT在 SQL 里拼接最直觀。5.5 MySQL 服務(wù)起不來3306 端口被占用現(xiàn)象執(zhí)行net start MySQL提示服務(wù)啟動(dòng)失敗或者后端啟動(dòng)時(shí)報(bào)Connection refused但 MySQL 服務(wù)明明顯示已啟動(dòng)。用netstat -ano查看3306 端口被某個(gè)進(jìn)程占用。原因本機(jī)之前裝過 MySQL舊服務(wù)還占著 3306或者另一個(gè)端口沖突。這類問題在機(jī)房電腦和二手筆記本上特別常見。解決# 查看 3306 端口被哪個(gè)進(jìn)程占用 netstat -ano | findstr 3306 # 找到 PID 后在任務(wù)管理器里結(jié)束進(jìn)程或命令行殺掉 taskkill /PID 1234 /F殺進(jìn)程前先確認(rèn)那個(gè) PID 到底是不是 MySQL有些機(jī)器上 3306 被其他數(shù)據(jù)庫占用。如果不想殺改當(dāng)前 MySQL 實(shí)例的端口修改my.ini里的port3307然后重啟服務(wù)同時(shí)把后端 JDBC URL 也改成 3307。我一般推薦后者因?yàn)榭梢员A舯緳C(jī)其他軟件的服務(wù)不動(dòng)課程作業(yè)環(huán)境少折騰為妙。6. 從交作業(yè)到能答辯給筆記系統(tǒng)加「智能」的進(jìn)階驗(yàn)證技巧6.1 搜索是「智能」的命門給筆記表加全文索引系統(tǒng)叫「智能筆記管理系統(tǒng)」但我的經(jīng)驗(yàn)里大部分交付版本只是 CRUD 加一個(gè)LIKE搜索。如果想讓答辯老師覺得這個(gè)名字有說服力最便宜的一步是把筆記搜索從LIKE升級(jí)為 MySQL 全文索引。數(shù)據(jù)量幾百條時(shí)LIKE還能忍但筆記內(nèi)容會(huì)越來越多全表掃描會(huì)越來越慢全文索引是 MySQL 原生支持、不需要引入額外組件的升級(jí)路線。ALTER TABLE note ADD FULLTEXT INDEX ft_note_title_content (title, content) WITH PARSER ngram; SELECT id, title, content FROM note WHERE MATCH(title, content) AGAINST(考研 筆記 IN NATURAL LANGUAGE MODE) AND is_delete 0;MySQL 5.7 之后支持中文全文索引但必須用ngram解析器否則中文分詞完全不工作。WITH PARSER ngram是關(guān)鍵字少了它索引對(duì)中文搜索等于沒加。IN NATURAL LANGUAGE MODE是最自然的匹配模式按相關(guān)度排序返回。這一步做完搜索體驗(yàn)從「精確匹配子串」直接變成「按關(guān)鍵詞相關(guān)度排序」效果上的差別是肉眼可見的。6.2 答辯演示腳本一條閉環(huán)路徑真到答辯時(shí)別一上來就點(diǎn)「登錄 — 退出」重復(fù)三遍。老師想看的是系統(tǒng)能完成一件完整的事。我給自己定的演示路徑是注冊(cè)新賬號(hào) → 新建兩個(gè)分類「工作」「讀書」 → 不同分類下各寫三條筆記 → 用全文搜索關(guān)鍵詞 → 編輯其中一條 → 刪除一條 → 在列表中確認(rèn)刪除后不再出現(xiàn) → 重新登錄確認(rèn)數(shù)據(jù)還在。# 演示前用一個(gè)請(qǐng)求快速驗(yàn)證后端存活 curl -X POST http://localhost:3000/api/user/login \ -H Content-Type: application/json \ -d {username:demo, password:123456}這條命令里的localhost:3000是前端代理地址能看到 200 和返回的 token 就說明前后端鏈路是通的。如果這里通了但頁面里操作失敗問題定位在前端代碼如果這里就不通說明要先回頭修后端。這個(gè)順序能幫你把「環(huán)境問題」和「代碼問題」快速切開不在黑匣子里瞎猜。我自己的教訓(xùn)是任何改動(dòng)哪怕只是改了一個(gè) SQL 條件都要先走一遍「新增一條含中文的內(nèi)容 → 列表刷新 → 搜索命中」三步閉環(huán)再上演示環(huán)境。環(huán)境折騰了一周最后因?yàn)橐粋€(gè)反向的LIKE參數(shù)現(xiàn)場翻車這種體驗(yàn)一次就夠。把這套系統(tǒng)當(dāng)成你將來的工具來驗(yàn)證而不是當(dāng)成交差作業(yè)來應(yīng)付它的「智能」屬性才有機(jī)會(huì)在答辯現(xiàn)場放光。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取