課程設(shè)計(jì):從環(huán)境搭建到源碼改造全攻略)
簡(jiǎn)介一份基于JavaWeb的新聞期刊管理系統(tǒng)課程設(shè)計(jì)資源適合計(jì)算機(jī)專業(yè)學(xué)生用于期末大作業(yè)、課程設(shè)計(jì)或畢業(yè)設(shè)計(jì)參考。資源包含完整項(xiàng)目源碼、配套設(shè)計(jì)報(bào)告和數(shù)據(jù)庫(kù)腳本系統(tǒng)涵蓋期刊列表展示、分類篩選、新聞詳情、后臺(tái)信息管理等典型功能模塊前端頁(yè)面基于Bootstrap進(jìn)行響應(yīng)式布局后端采用JSP配合JavaBean/Servlet方式實(shí)現(xiàn)分層開(kāi)發(fā)報(bào)告內(nèi)還寫(xiě)明設(shè)計(jì)流程與關(guān)鍵代碼說(shuō)明。壓縮包共三百三十九個(gè)文件包含Java源碼、JSP頁(yè)面、XML配置、CSS樣式、JS腳本及SQL數(shù)據(jù)庫(kù)腳本等程序文件另有PNG圖片和JPG圖片素材包體大小約七十八點(diǎn)一兆目錄結(jié)構(gòu)清晰導(dǎo)入開(kāi)發(fā)工具并執(zhí)行數(shù)據(jù)庫(kù)腳本即可運(yùn)行。目前已有七百二十八人學(xué)習(xí)下載其中不少人以此獲得高分課設(shè)答辯成績(jī)相當(dāng)于獲得一個(gè)可直接演示、便于二次改寫(xiě)的完整項(xiàng)目樣板。1. JavaWeb新聞期刊管理系統(tǒng)課程設(shè)計(jì)壓縮包里到底裝著什么跑起來(lái)能解決什么問(wèn)題這套基于JavaWeb的新聞期刊管理系統(tǒng)壓縮包裝的是課程設(shè)計(jì)的三件套JavaWeb項(xiàng)目源碼、課程設(shè)計(jì)報(bào)告和數(shù)據(jù)庫(kù)腳本。系統(tǒng)本身是經(jīng)典的 JSP Servlet JDBC MySQL 三層結(jié)構(gòu)功能?chē)@新聞和期刊的后臺(tái)管理展開(kāi)包括管理員登錄、新聞發(fā)布與編輯、期刊欄目維護(hù)、用戶權(quán)限控制等。它能解決的任務(wù)很直接課程設(shè)計(jì)階段你需要一個(gè)能演示、能答辯、還能二次改動(dòng)的完整java課程設(shè)計(jì)案例源碼而不是自己從零堆一個(gè)只能跑通一半的半成品。適合正在交JavaWeb課程設(shè)計(jì)的學(xué)生也適合想讀懂一個(gè)完整JavaWeb項(xiàng)目再動(dòng)手改寫(xiě)的入門(mén)開(kāi)發(fā)者。下面按跑通、讀碼、避坑、改造、驗(yàn)證的順序講完整閉環(huán)。2. 從壓縮包到瀏覽器出現(xiàn)登錄頁(yè)環(huán)境準(zhǔn)備、IDEA 導(dǎo)入、數(shù)據(jù)庫(kù)初始化2.1 技術(shù)棧與版本選擇JDK 8、Tomcat 8.5、MySQL 5.7 的搭配邏輯先說(shuō)技術(shù)底座。這套新聞期刊管理系統(tǒng)不是 SpringBoot 全家桶而是比較純粹的 JavaWeb 三層項(xiàng)目JSP 負(fù)責(zé)頁(yè)面Servlet 接收請(qǐng)求DAO 用 JDBC 操作 MySQL。運(yùn)行它只需要四樣?xùn)|西JDK、Tomcat、MySQL、IDEA。版本組合我會(huì)首選 JDK 8 Tomcat 8.5 MySQL 5.7這套組合對(duì)老項(xiàng)目兼容性最好幾乎不用改配置就能跑。為什么這樣選JDK 8 是 JavaWeb 課程設(shè)計(jì)的絕對(duì)主流源碼的編譯級(jí)別、Servlet API 依賴基本都是按這個(gè)基線寫(xiě)的Tomcat 8.5 對(duì)應(yīng) Servlet 3.1 規(guī)范javax.servlet 的包名不用改換成 Tomcat 10 就得把 javax 改成 jakarta工作量瞬間變大MySQL 5.7 對(duì)課程設(shè)計(jì)時(shí)代導(dǎo)出的 .sql 腳本兼容性最穩(wěn)建表語(yǔ)句、字段類型、編碼設(shè)置在 5.7 里基本無(wú)腦通過(guò)。用 MySQL 8.0 也不是不行但你會(huì)多踩兩個(gè)坑連接時(shí)區(qū)警告和密碼加密插件不匹配。動(dòng)手之前先做一次環(huán)境體檢命令行輸入兩段驗(yàn)證java -version mysql --version如果 java 版本輸出的是 17 或更高建議額外裝一個(gè) JDK 8并把 JAVA_HOME 指向它。Tomcat 不需要安裝解壓到固定目錄讓 IDEA 直接引用這個(gè)目錄。環(huán)境變量配置完重新打開(kāi)終端再驗(yàn)證一次這條是經(jīng)常讓人自我懷疑的玄學(xué)點(diǎn)配完 JAVA_HOME 不刷新 shell執(zhí)行命令怎么看都像沒(méi)生效其實(shí)是終端緩存了舊 PATH。配置環(huán)境變量的參考寫(xiě)法Windows 下系統(tǒng)變量里新增JAVA_HOMEC:\Program Files\Java\jdk1.8.0_202 PATH%JAVA_HOME%\bin;%PATH%2.2 IDEA 導(dǎo)入源碼并配置 Tomcat四個(gè)必改的配置點(diǎn)拿到壓縮包后先做兩件事。第一解壓到純英文路徑比如 D:\workspace\news-system路徑里混入中文會(huì)引發(fā) Tomcat 虛擬目錄和字符編碼的詭異問(wèn)題屬于能避開(kāi)就別硬剛的坑。第二掃一眼包結(jié)構(gòu)一般會(huì)看到 src 源碼目錄、WebContent 或 web 前端目錄、lib 依賴目錄、數(shù)據(jù)庫(kù) .sql 腳本還有課程設(shè)計(jì)報(bào)告文檔。用 IDEA 打開(kāi)項(xiàng)目時(shí)我建議直接用 Open 而不是 New ProjectOpen 會(huì)盡量沿用已有結(jié)構(gòu)少讓 IDEA 瞎猜。項(xiàng)目加載完進(jìn)入 Project Structure快捷鍵 CtrlAltShiftS按順序檢查四個(gè)配置點(diǎn)。第一是 Project SDK選到 JDK 8Language Level 同步調(diào)到 8。第二是 Facets 里的 Web 模塊IDEA 經(jīng)常識(shí)別不出老項(xiàng)目里的 WebContent 目錄需要手動(dòng)添加 Web Facet把 Web Resource Directory 指到實(shí)際的前端目錄。第三是 Artifacts右鍵新建 Web Application Exploded然后看 Output Layout確認(rèn)依賴 jar 都打進(jìn)了 WEB-INF/libmysql 驅(qū)動(dòng)、jstl、standard 這幾個(gè) jar 一旦缺失運(yùn)行時(shí)必然 ClassNotFound。第四是 Tomcat 運(yùn)行配置Run → Edit Configurations → 新增 Tomcat Server → LocalApplication Server 選 Tomcat 目錄Deployment 里把這個(gè)項(xiàng)目 Artifact 添加進(jìn)去再設(shè)置 Application context。四個(gè)點(diǎn)都處理完點(diǎn)擊運(yùn)行。Tomcat 啟動(dòng)日志正常出現(xiàn)后瀏覽器訪問(wèn) http://localhost:8080/項(xiàng)目名/能看到首頁(yè)或登錄頁(yè)就算把項(xiàng)目帶起來(lái)了。Application context 最容錯(cuò)配錯(cuò)。源碼里所有鏈接寫(xiě)成 /news-system/login.jsp 這種絕對(duì)路徑context 就要設(shè)成 /news-system源碼里用相對(duì)路徑context 留空或?qū)?/。判斷方法很簡(jiǎn)單打開(kāi)一個(gè) JSP 看表單 action 的前綴跟 Deployment 里的 context 保持一致就不會(huì)頁(yè)面 404。2.3 數(shù)據(jù)庫(kù)腳本導(dǎo)入與 JDBC 連接串修改數(shù)據(jù)庫(kù)初始化是最后一道關(guān)卡。壓縮包里通常會(huì)有一個(gè) .sql 腳本多數(shù)情況下在根目錄或 database 文件夾。導(dǎo)入前先建庫(kù)再執(zhí)行腳本mysql -u root -p -e CREATE DATABASE IF NOT EXISTS news_mag DEFAULT CHARACTER SET utf8mb4; mysql -u root -p news_mag D:\workspace\news-system\news_mag.sql第二條命令的路徑換成壓縮包里實(shí)際腳本的路徑。如果本機(jī)沒(méi)有 mysql 命令行用 Navicat 或 IDEA 自帶的 Database 面板手工執(zhí)行也完全可以先建庫(kù)再把 .sql 文件拖進(jìn)控制臺(tái)執(zhí)行。導(dǎo)入完建議執(zhí)行一行 show tables;確認(rèn)新聞表、期刊表、用戶表、欄目表這些核心表都在缺表多半是腳本執(zhí)行到一半報(bào)錯(cuò)中斷。數(shù)據(jù)庫(kù)就緒后打開(kāi)源碼里負(fù)責(zé)連接的工具類常見(jiàn)命名是 JDBCUtils、DBUtil、JdbcUtil也可能獨(dú)立存在一個(gè) jdbc.properties 配置文件。搜索 DriverManager.getConnection 或配置文件里的 url 字段把它改成當(dāng)前環(huán)境值jdbc.urljdbc:mysql://localhost:3306/news_mag?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password你的密碼連接串里的 characterEncoding 和 serverTimezone 是重點(diǎn)參數(shù)前者解決中文寫(xiě)入亂碼后者解決 MySQL 8.0 時(shí)區(qū)報(bào)錯(cuò)。改完重啟 Tomcat用初始管理員賬號(hào)登錄后臺(tái)能進(jìn)控制臺(tái)首頁(yè)就說(shuō)明整套環(huán)境跑通了。到這里壓縮包已經(jīng)變成一臺(tái)你自己的可演示 JavaWeb 完整案例。3. 源碼走讀登錄、新聞管理、期刊管理的核心鏈路3.1 項(xiàng)目目錄結(jié)構(gòu)與三層架構(gòu)的職責(zé)劃分項(xiàng)目跑起來(lái)之后下一步是讀代碼。讀這種課程設(shè)計(jì)源碼別從頭到尾逐行啃而是先建一張心理地圖。典型目錄結(jié)構(gòu)是 src 下分 entity、dao、service、servlet、filter、util 這幾個(gè)包前端頁(yè)面在 WebContent 或 web 目錄下。每層只做一件事entity 是數(shù)據(jù)庫(kù)表的 Java 映射字段名和表結(jié)構(gòu)基本一一對(duì)應(yīng)dao 層只寫(xiě) SQL 和 JDBC 操作決定數(shù)據(jù)怎么存取service 層編排業(yè)務(wù)邏輯比如登錄校驗(yàn)、參數(shù)格式、事務(wù)控制servlet 層處理 HTTP 請(qǐng)求的接收、參數(shù)解析、跳轉(zhuǎn)轉(zhuǎn)發(fā)filter 做編碼過(guò)濾和登錄攔截。調(diào)用方向是 JSP → Servlet → Service → DAO → MySQL反過(guò)來(lái)讀代碼時(shí)從數(shù)據(jù)庫(kù)表往 servlet 方向看思路會(huì)順暢很多。我讀這種項(xiàng)目的固定順序是先打開(kāi)數(shù)據(jù)庫(kù)工具看表結(jié)構(gòu)確認(rèn)新聞表、期刊表、用戶表、欄目表之間的關(guān)系再回到 dao 包翻 SQL看每個(gè)模塊的增刪改查最后打開(kāi) servlet把請(qǐng)求路徑和數(shù)據(jù)流串起來(lái)。一個(gè)模塊比如新聞管理核心文件不超過(guò)十個(gè)一次就能看明白完整閉環(huán)。3.2 一條新聞發(fā)布請(qǐng)求從 JSP 走到 MySQLServlet、Service、DAO 的分工以“新增新聞”為例這條請(qǐng)求能穿透整套三層架構(gòu)。當(dāng)管理員在 news_add.jsp 里填完標(biāo)題、欄目、內(nèi)容點(diǎn)提交form 的 action 會(huì)指向某個(gè) Servlet比如 /NewsAddServlet。Servlet 的 doPost 方法通常長(zhǎng)這樣protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String title request.getParameter(title); String content request.getParameter(content); int categoryId 0; if (request.getParameter(categoryId) ! null) { categoryId Integer.parseInt(request.getParameter(categoryId)); } News news new News(); news.setTitle(title); news.setContent(content); news.setCategoryId(categoryId); boolean ok newsService.addNews(news); if (ok) { response.sendRedirect(newsList); } else { request.setAttribute(errorMsg, 添加失敗); request.getRequestDispatcher(/admin/news_add.jsp).forward(request, response); } }setCharacterEncoding 必須放在取參數(shù)之前否則 POST 提交的中文會(huì)亂掉這是老項(xiàng)目最常見(jiàn)的隱性 bug。Integer.parseInt 之前最好做一次空值判斷否則參數(shù)缺失時(shí)直接拋 NumberFormatException頁(yè)面 500。Service 層的 addNews 一般做業(yè)務(wù)校驗(yàn)和透?jìng)髡n程設(shè)計(jì)項(xiàng)目里不一定有完整事務(wù)但至少要返回 boolean 給 Servlet 判斷成功與否。DAO 層的關(guān)鍵 SQL 值得單獨(dú)看因?yàn)?SQL 寫(xiě)法直接決定安不安全String sql INSERT INTO news (title, content, category_id, create_time) VALUES (?, ?, ?, NOW()); try (PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, news.getTitle()); ps.setString(2, news.getContent()); ps.setInt(3, news.getCategoryId()); return ps.executeUpdate() 0; }這里用 PreparedStatement 的 ? 占位符做參數(shù)綁定setString 和 setInt 會(huì)幫你處理轉(zhuǎn)義和類型轉(zhuǎn)換從根上避免 SQL 注入。如果源碼里用的是字符串拼接 SQL答辯時(shí)這是明顯的減分點(diǎn)照著上面改回去成本很低屬于十五分鐘能完成的必修改造。3.3 登錄會(huì)話、角色權(quán)限與期刊管理的實(shí)現(xiàn)登錄模塊是答辯必講點(diǎn)。大多數(shù)課程設(shè)計(jì)版本都有一張管理員表登錄 Servlet 驗(yàn)證用戶名密碼后把用戶對(duì)象放進(jìn) SessionUser user userService.login(username, md5(password)); if (user ! null) { request.getSession().setAttribute(loginUser, user); response.sendRedirect(admin/index.jsp); } else { request.setAttribute(errorMsg, 用戶名或密碼錯(cuò)誤); request.getRequestDispatcher(login.jsp).forward(request, response); }把密碼轉(zhuǎn)成 MD5 再比對(duì)已經(jīng)是老項(xiàng)目里的入門(mén)操作答辯時(shí)如果老師追問(wèn)你可以再補(bǔ)一句“正式環(huán)境還要加鹽”。后臺(tái)權(quán)限控制靠 Filter 攔擊HttpSession session request.getSession(); User user (User) session.getAttribute(loginUser); if (user null) { response.sendRedirect(login.jsp); return; } chain.doFilter(request, response);這段邏輯本身不難難在放行路徑。登錄頁(yè)面、登錄 Servlet、css、js、圖片這些靜態(tài)資源必須排除在攔截規(guī)則外否則頁(yè)面樣式全丟登錄請(qǐng)求也會(huì)被重定向循環(huán)。通常在 Filter 里用 request.getRequestURI() 判斷前綴把 /login.jsp、/css/、/js/、/images/ 放行。期刊管理和新聞管理的代碼骨架幾乎一樣區(qū)別集中在業(yè)務(wù)字段上期刊一般會(huì)多出期號(hào)、出版日期、封面圖片、PDF 附件所以新增期刊的表單要用 enctypemultipart/form-data后端讀取文件用 Part 接口或 commons-fileupload。如果壓縮包里的期刊模塊沒(méi)做上傳這反而是個(gè)很好用的改造點(diǎn)一個(gè)上傳封面的功能就夠讓答辯演示變豐滿。4. 常見(jiàn)運(yùn)行問(wèn)題與避坑排查5 個(gè) JavaWeb 課程設(shè)計(jì)翻車(chē)點(diǎn)4.1 啟動(dòng)部署階段端口占用、NotFound 與依賴丟失翻車(chē)點(diǎn)一Tomcat 啟動(dòng)失敗控制臺(tái)報(bào) Address already in use。現(xiàn)象是點(diǎn)擊運(yùn)行后幾秒內(nèi)報(bào)端口占用異常瀏覽器連不上服務(wù)。原因大多是之前有殘留的 Tomcat 進(jìn)程沒(méi)殺掉或者本機(jī)裝了多個(gè) Tomcat 同時(shí)搶 8080 端口。解決分兩步先找到占用端口的進(jìn)程再?zèng)Q定殺進(jìn)程還是換端口netstat -ano | findstr 8080 taskkill /pid 進(jìn)程號(hào) /F不想動(dòng)進(jìn)程的話可以在 IDEA 的 Tomcat 配置里把 HTTP port 改成 8081訪問(wèn)地址同步變化。翻車(chē)點(diǎn)二項(xiàng)目訪問(wèn) 404或者報(bào) ClassNotFoundException。現(xiàn)象是 Tomcat 能正常啟動(dòng)默認(rèn)首頁(yè)也能打開(kāi)但輸入項(xiàng)目路徑永遠(yuǎn)是 404點(diǎn)登錄則拋 ClassNotFoundException集中在 mysql 驅(qū)動(dòng)和 jstl 兩個(gè)庫(kù)。原因通常是 Artifact 沒(méi)完整構(gòu)建或者依賴 jar 沒(méi)有打進(jìn) WEB-INF/lib。解決方式先到 Run → Edit Configurations 確認(rèn) Deployment 列表里有這個(gè)項(xiàng)目再檢查 Project Structure → Artifacts → Output Layout把 lib 下缺失的 jar 手動(dòng)添加上最后 Build → Rebuild Project 重新構(gòu)建。4.2 數(shù)據(jù)庫(kù)階段連接失敗與中文亂碼翻車(chē)點(diǎn)三數(shù)據(jù)庫(kù)連接失敗報(bào) Communications link failure 或 Access denied?,F(xiàn)象是登錄后臺(tái)時(shí)頁(yè)面 500控制臺(tái)一堆連接 MySQL 的異常棧。原因按概率排序是MySQL 服務(wù)沒(méi)啟動(dòng)、連接串里的賬號(hào)密碼寫(xiě)錯(cuò)、驅(qū)動(dòng)版本不匹配、連接串缺時(shí)區(qū)參數(shù)。解決先驗(yàn)證數(shù)據(jù)庫(kù)本體命令行執(zhí)行 mysql -u root -p -e select 1;能通就排除服務(wù)問(wèn)題再核對(duì) JDBC 連接串密碼和庫(kù)名是最容易被抄錯(cuò)的兩個(gè)值最后確認(rèn)驅(qū)動(dòng) jar 版本代碼里寫(xiě) com.mysql.jdbc.Driver 就用驅(qū)動(dòng) 5.1.x寫(xiě)成 com.mysql.cj.jdbc.Driver 就換驅(qū)動(dòng) 8.0.x并補(bǔ)上 serverTimezoneAsia/Shanghai。翻車(chē)點(diǎn)四頁(yè)面和后臺(tái)中文全部是問(wèn)號(hào)?,F(xiàn)象是新聞標(biāo)題、期刊名稱、菜單文字變成 ?? 或方框前端 HTML 源碼里卻能看到中文。原因是三層編碼不統(tǒng)一JSP 頁(yè)面編碼、數(shù)據(jù)庫(kù)表字符集、Servlet 請(qǐng)求編碼缺一個(gè) UTF-8。解決方式是把三層對(duì)齊JSP 頭部 pageEncodingUTF-8Servlet 在 doGet 和 doPost 開(kāi)頭都調(diào) request.setCharacterEncoding(UTF-8)數(shù)據(jù)庫(kù)建庫(kù)時(shí)指定 DEFAULT CHARACTER SET utf8mb4。改完重啟 Tomcat 還不行就 DROP 掉表重新執(zhí)行 .sql 導(dǎo)入因?yàn)閬y碼數(shù)據(jù)一旦寫(xiě)進(jìn)表里不會(huì)自己恢復(fù)。4.3 業(yè)務(wù)功能階段圖片上傳不顯示與會(huì)話失效翻車(chē)點(diǎn)五新聞或期刊封面上傳成功后圖片在頁(yè)面上裂開(kāi)。現(xiàn)象是上傳返回成功但 img 標(biāo)簽里的 src 指向磁盤(pán)路徑瀏覽器訪問(wèn)不到。原因是上傳文件被寫(xiě)到了 Tomcat 部署目錄之外的磁盤(pán)位置項(xiàng)目無(wú)法用相對(duì)路徑訪問(wèn)。解決優(yōu)先改代碼把上傳目錄改到項(xiàng)目的 upload 目錄下頁(yè)面引用相對(duì)路徑如果不想動(dòng)代碼也可以給 Tomcat 配置虛擬目錄在 conf/server.xml 里加 Context 把物理路徑映射到 /upload 虛路徑。課程設(shè)計(jì)階段推薦前者改動(dòng)量小且不污染 Tomcat 配置。補(bǔ)充一個(gè)會(huì)話問(wèn)題登錄后沒(méi)多久就跳回登錄頁(yè)常見(jiàn)的現(xiàn)象是 Tomcat 默認(rèn) Session 超時(shí) 30 分鐘但代碼里可能被顯式設(shè)成 60 秒。搜源碼里的 setMaxInactiveInterval把這個(gè)值改成 1800 秒或者直接刪掉。5. 課程設(shè)計(jì)報(bào)告對(duì)照與低風(fēng)險(xiǎn)改造把模板項(xiàng)目變成有記憶點(diǎn)的答辯作品5.1 報(bào)告章節(jié)與源碼的對(duì)應(yīng)關(guān)系需求分析、數(shù)據(jù)庫(kù)設(shè)計(jì)、系統(tǒng)實(shí)現(xiàn)分別看哪里課程設(shè)計(jì)報(bào)告是壓縮包里最容易被忽略但價(jià)值最高的部分它本質(zhì)上是答辯提綱。打開(kāi)報(bào)告每章都能在源碼里找到對(duì)應(yīng)物需求分析對(duì)應(yīng)系統(tǒng)菜單模塊去數(shù)一下登錄、新聞管理、期刊管理、欄目分類、用戶管理是否都有實(shí)現(xiàn)數(shù)據(jù)庫(kù)設(shè)計(jì)對(duì)應(yīng)真實(shí)表結(jié)構(gòu)報(bào)告里的 ER 圖和數(shù)據(jù)字典應(yīng)該和數(shù)據(jù)庫(kù)里的字段一致詳細(xì)設(shè)計(jì)對(duì)應(yīng) Servlet 和 Service 的類名測(cè)試章節(jié)對(duì)應(yīng)你能在瀏覽器里跑通的真實(shí)操作路徑。最劃算的準(zhǔn)備工作是把報(bào)告里的數(shù)據(jù)庫(kù)設(shè)計(jì)圖和真實(shí)表結(jié)構(gòu)對(duì)齊。用 Navicat、IDEA Database 面板或 MySQL Workbench 導(dǎo)出一張 ER 圖跟報(bào)告里的圖做對(duì)比有出入就按源碼實(shí)際結(jié)構(gòu)改文檔。答辯投影時(shí)直接放真實(shí) ER 圖講新聞表和期刊表的關(guān)系比念一段文字有力得多。我一般還會(huì)把報(bào)告里“系統(tǒng)實(shí)現(xiàn)”章節(jié)截幾張關(guān)鍵頁(yè)面圖重新截圖替換避免出現(xiàn)代碼版本和截圖對(duì)不上的尷尬。5.2 低風(fēng)險(xiǎn)改造一登錄密碼從明文比對(duì)改成 MD5 加鹽模板項(xiàng)目里最常見(jiàn)的安全短板是密碼明文存儲(chǔ)或只做一次簡(jiǎn)單 MD5。答辯時(shí)老師一問(wèn)“密碼怎么存的”回答“明文”基本等于被判死緩。低成本改造是在工具類里加一個(gè)加鹽哈希方法public static String saltMd5(String password, String salt) { String s salt password; for (int i 0; i 5; i) { s MD5Util.md5(s); } return s; }注冊(cè)時(shí)給每個(gè)用戶生成隨機(jī) salt 存到單獨(dú)字段登錄時(shí)用同一個(gè) salt 算哈希再比對(duì)。改動(dòng)集中在用戶表和登錄、注冊(cè)兩個(gè)方法風(fēng)險(xiǎn)很小。答辯時(shí)能主動(dòng)說(shuō)出“密碼我做了加鹽處理”安全分立刻不一樣。5.3 低風(fēng)險(xiǎn)改造二給新聞列表加關(guān)鍵詞搜索很多模板項(xiàng)目只有菜單和全量列表沒(méi)有搜索能力。加一個(gè)搜索框是改動(dòng)范圍小、演示效果好的改造。先在新聞列表頁(yè)加一個(gè)輸入框Servlet 接收 keyword 參數(shù)DAO 層查詢改成 LIKE 模糊匹配String sql SELECT * FROM news WHERE title LIKE ? OR content LIKE ? ORDER BY create_time DESC; try (PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); ps.setString(2, % keyword %); ResultSet rs ps.executeQuery(); }% 放在 keyword 前后表示標(biāo)題或內(nèi)容里任意位置包含該關(guān)鍵詞都命中。如果列表本身沒(méi)有分頁(yè)可以順手加一句 LIMIT offset, size一次改造把搜索和分頁(yè)都補(bǔ)齊。改完一定要用中文關(guān)鍵詞測(cè)試搜出來(lái)是 ?? 等于白做回到第 4 章的亂碼排查流程再查一遍編碼。6. 答辯演示前的驗(yàn)證技巧用一條完整業(yè)務(wù)鏈路跑出兜底方案6.1 用主流程五步完成冒煙測(cè)試答辯前一天別只點(diǎn)開(kāi)頁(yè)面看兩眼把系統(tǒng)當(dāng)真實(shí)用戶從頭到尾走一遍完整鏈路。我習(xí)慣的冒煙順序訪問(wèn)登錄頁(yè) → 輸入管理員賬號(hào)登錄 → 后臺(tái)首頁(yè)點(diǎn)開(kāi)新聞管理 → 新增一篇帶明顯測(cè)試字樣的新聞 → 在列表里搜索這個(gè)關(guān)鍵詞 → 點(diǎn)擊詳情修改一個(gè)字段 → 刪除這篇數(shù)據(jù)。整個(gè)過(guò)程走通項(xiàng)目的核心鏈路就驗(yàn)證完畢了。任何一步報(bào)錯(cuò)立刻回到對(duì)應(yīng)章節(jié)排查把配置問(wèn)題留在演示之前解決。6.2 兩個(gè)兜底技巧錄回放、備數(shù)據(jù)庫(kù)快照只靠現(xiàn)場(chǎng)演示有不確定性數(shù)據(jù)庫(kù)連接、瀏覽器緩存、課堂投影都可能給你整活。我的血淚經(jīng)驗(yàn)是提前做兩件事第一把整個(gè)冒煙過(guò)程用錄屏工具錄成短視頻存到 U 盤(pán)現(xiàn)場(chǎng)真翻車(chē)時(shí)直接放回放畫(huà)面和節(jié)奏完全受控第二用 mysqldump 把當(dāng)前數(shù)據(jù)庫(kù)導(dǎo)出一份快照文件萬(wàn)一演示現(xiàn)場(chǎng)數(shù)據(jù)被改壞一條命令就能恢復(fù)成完整狀態(tài)mysqldump -u root -p news_mag news_mag_backup.sql這份備份文件本身也能作為“數(shù)據(jù)庫(kù)設(shè)計(jì)完成度”的物證放在課程設(shè)計(jì)報(bào)告附件里是加分項(xiàng)。回頭來(lái)看當(dāng)時(shí)第一次演示翻車(chē)就是因?yàn)闆](méi)走完整冒煙鏈路、現(xiàn)場(chǎng)新增新聞時(shí)發(fā)現(xiàn)欄目參數(shù)沒(méi)傳后來(lái)我養(yǎng)成了所有演示前先全局跑一遍的習(xí)慣把不確定性盡量留在調(diào)試階段。這個(gè)習(xí)慣希望能幫到你少一次現(xiàn)場(chǎng)意外多一分答辯底氣。本文還有配套的精品資源點(diǎn)擊獲取