畢設(shè)實戰(zhàn):從數(shù)據(jù)庫設(shè)計到核心業(yè)務(wù)代碼)
最近遇到好幾個準(zhǔn)備計算機畢業(yè)設(shè)計的同學(xué)都在找SSM房屋裝修管理系統(tǒng)的源碼和實現(xiàn)文檔。這個題目我在帶的課程設(shè)計里也完整走過一遍所以單獨寫一篇把從需求到數(shù)據(jù)庫再到核心業(yè)務(wù)代碼的整套思路都拆開講講。房屋裝修管理系統(tǒng)不是簡單的新增刪除它把業(yè)主、裝修公司、管理員三個角色串在一條業(yè)務(wù)線上業(yè)主發(fā)裝修需求公司報價雙方簽合同然后施工、報進度、驗收、評價。對于一個畢設(shè)來說它比普通的學(xué)生管理、圖書管理更能體現(xiàn)完整的業(yè)務(wù)閉環(huán)答辯時也更有東西可講。這篇文章適合正在做JavaWeb畢業(yè)設(shè)計、需要快速理解SSM項目或者準(zhǔn)備用這套源碼二改的同學(xué)看完之后你至少能說清楚每一張表是干什么的每個核心接口是怎么流轉(zhuǎn)的。1. 畢設(shè)選題里的安全牌為什么SSM加裝修管理仍然能打1.1 選題同質(zhì)化嚴重裝修管理好在哪每年畢業(yè)設(shè)計提交上來打開一看一半是校園二手交易平臺一半是圖書管理系統(tǒng)剩下的是各種商城。不是說這些題目不好而是太容易撞車開題、答辯、論文查重的時候都很痛苦。房屋裝修管理系統(tǒng)的好處在于它有一個真實的行業(yè)場景業(yè)務(wù)流程比單一模塊的CRUD復(fù)雜一點但又不至于復(fù)雜到做不完。裝修行業(yè)里有一個天然的多角色協(xié)作鏈條業(yè)主想裝修裝修公司想接單中間有報價、合同、施工、驗收、評價。這個鏈條本身就是一套狀態(tài)機需求先等待報價報價后等待業(yè)主確認確認后生成合同合同開始施工施工階段要不斷更新進度最后驗收。每個狀態(tài)變化都對應(yīng)一個業(yè)務(wù)動作每個動作都會落到數(shù)據(jù)庫的某個表上。做這種系統(tǒng)論文里能畫出清晰的業(yè)務(wù)流程圖、用例圖、時序圖代碼里能體現(xiàn)多表關(guān)聯(lián)、事務(wù)控制、權(quán)限攔截比單純做一張圖書表有意義得多。1.2 SSM不是新技術(shù)但依然是畢業(yè)答辯里的穩(wěn)妥選擇很多同學(xué)會問為什么不直接用SpringBoot如果學(xué)校允許用SpringBoot當(dāng)然更省事配置少、開發(fā)快。但如果你所在學(xué)校課程體系里教的是SSM或者指導(dǎo)老師對框架底層比較看重那SSM反而是更穩(wěn)妥的選擇。原因很簡單SSM需要你自己維護Spring的applicationContext.xml、SpringMVC的配置文件、MyBatis的Mapper映射這套配置過程能夠逼著你搞清楚Spring容器怎么啟動、DispatcherServlet如何攔截請求、SqlSessionFactory是怎么構(gòu)建的。答辯時老師問一句SpringMVC的執(zhí)行流程是什么你配置過、Debug過就能順著DispatcherServlet、HandlerMapping、Controller、ViewResolver一條線講下來。換成SpringBoot很多配置被自動裝配隱藏掉了遇到同樣的問題反而容易答不上來。用SSM實現(xiàn)房屋裝修管理系統(tǒng)代碼量會比SpringBoot大一些但是可控性很高。這個項目我測試過多次Tomcat 8.5加JDK 1.8跑得很穩(wěn)適合作為計算機畢業(yè)設(shè)計原創(chuàng)源碼去交付。1.3 源碼不是終點拿到手第一件事別急著運行凡是帶贈源碼字樣的畢設(shè)項目我都會提醒一句話源碼是用來學(xué)習(xí)不是用來直接交的。你把它下載下來以后第一步不是雙擊打開數(shù)據(jù)庫腳本一頓執(zhí)行而是先花一晚上把目錄結(jié)構(gòu)、核心表設(shè)計、請求路由看明白。我看過太多同學(xué)答辯前一周才開始看源碼結(jié)果連項目怎么啟動都不知道更別提演示的時候突然報錯。帶著源碼跑一遍只是會用能說清楚每個表字段為什么這樣設(shè)計、每個接口為什么這樣寫才是懂。這篇博文后面的內(nèi)容就是幫你從能跑走到能講。2. 需求分析不能拍腦袋裝修管理到底在管哪些事2.1 三角色與核心用例需求分析階段最容易犯的錯誤是上來就畫頁面、寫字段。正確的做法是先梳理角色和用例。這套系統(tǒng)里最核心的角色有三個業(yè)主客戶、裝修公司、系統(tǒng)管理員。角色核心操作典型訴求業(yè)主注冊登錄、發(fā)布裝修需求、查看報價、確認合同、查看施工進度、驗收、評價找靠譜公司、控制預(yù)算、知道施工到哪一步裝修公司注冊登錄、查看需求、報價、接受合同、上報進度、提交驗收接到更多訂單、展示公司實力、及時同步施工情況系統(tǒng)管理員用戶管理、需求審核、公告發(fā)布、數(shù)據(jù)統(tǒng)計維護系統(tǒng)秩序、確保信息真實上網(wǎng)搜索或者看真實的裝修平臺會發(fā)現(xiàn)有些系統(tǒng)還會拆出設(shè)計師工長監(jiān)理但畢設(shè)不建議拆太細。角色越多權(quán)限控制和頁面開發(fā)工作量成倍上升。三個角色足夠形成業(yè)務(wù)差異也足夠在答辯時講清楚權(quán)限設(shè)計。2.2 一條完整的業(yè)務(wù)閉環(huán)把這套系統(tǒng)的業(yè)務(wù)閉環(huán)畫成流程應(yīng)該是這樣業(yè)主發(fā)布裝修需求填寫房屋面積、戶型、裝修風(fēng)格、預(yù)算范圍、期望開工時間等基本信息。需求庫里的裝修公司可以瀏覽這些需求有合適的就發(fā)起報價。業(yè)主看到多個報價后選擇合適的公司雙方自動進入合同簽訂環(huán)節(jié)。合同生成之后裝修公司會按施工階段持續(xù)上報進度比如拆改階段、水電階段、泥瓦階段業(yè)主可以在系統(tǒng)里看到進度百分比和文字描述。施工完成后裝修公司申請驗收業(yè)主確認通過后可以針對本次裝修寫評價整條鏈路才算結(jié)束。你在答辯時如果能把這個閉環(huán)用一兩分鐘講出來老師立刻知道你不是在做一個零散的增刪改查系統(tǒng)。2.3 功能清單與判定標(biāo)準(zhǔn)需求分析之后要整理出一份功能清單。這里有個原則基礎(chǔ)功能要形成閉環(huán)加分功能量力而行。基礎(chǔ)功能包括用戶注冊登錄、需求發(fā)布與列表查詢、報價管理、合同管理、施工進度管理、驗收管理、評價管理、后臺用戶管理。這些已經(jīng)能支撐一個完整的裝修業(yè)務(wù)流程。加分功能包括密碼加密存儲、攔截器權(quán)限校驗、公告管理、需求多條件篩選、合同編號自動生成、列表分頁顯示。如果時間和能力允許可以再加統(tǒng)計報表和文件上傳。我在給課程設(shè)計做驗收時最看重的是狀態(tài)流轉(zhuǎn)是否閉環(huán)。很多項目看起來功能都有但需求發(fā)布完以后報價和合同之間沒有關(guān)聯(lián)進度和合同之間也連不上這在老師眼里就是兩張獨立的表硬湊成一個系統(tǒng)。你寧可功能少一點也要保證主流程是通的。3. 數(shù)據(jù)庫表設(shè)計復(fù)盤如何用9張表撐起整個系統(tǒng)3.1 用戶角色與公司信息的設(shè)計取舍數(shù)據(jù)庫設(shè)計是整個SSM房屋裝修管理系統(tǒng)的地基。我給的參考方案是9張核心表這在本項目源碼里可以對應(yīng)看到。第一組是用戶表建議命名為t_user。字段包含id、username、password、real_name、phone、role、avatar、create_time。其中role用整型區(qū)分角色比如0表示管理員、1表示業(yè)主、2表示裝修公司。這樣一張表完成登錄認證簡單直接。裝修公司不建議和用戶表合并成一張大表。雖然業(yè)務(wù)上裝修公司也是一個賬號但公司有公司名稱、營業(yè)執(zhí)照編號、地址、介紹、評分等信息和普通業(yè)主差異很大。如果全部塞進t_user字段會很臃腫而且不符合單一職責(zé)的表設(shè)計原則。所以單獨建一張t_company表字段包括id、user_id、company_name、license_no、contact_person、address、intro、rating。user_id與t_user.id建立一對一關(guān)聯(lián)既保留了賬號登錄獨立性也能在裝修需求列表頁方便地顯示公司名稱。3.2 業(yè)務(wù)主鏈需求、報價、合同第二組是業(yè)務(wù)主鏈上的三張表需求表t_demand、報價表t_quote、合同表t_contract。t_demand是業(yè)主發(fā)布需求的落點核心字段有id、user_id、house_area、house_layout、decoration_style、budget、description、province/city/address、status、create_time。status請一定用int建議定義成0待接單、1已報價、2已簽約、3施工中、4待驗收、5已完成、6已關(guān)閉。t_quote是裝修公司對某條需求發(fā)起的報價核心字段id、demand_id、company_id、price、duration_days、plan_content、status、create_time。demand_id關(guān)聯(lián)需求表company_id關(guān)聯(lián)公司表。status可以定義成0待業(yè)主確認、1已接受、2已拒絕。注意這里的設(shè)計邏輯一條需求可以被多家公司報價所以t_demand和t_quote是一對多關(guān)系。t_contract生成時機是業(yè)主接受了某條報價。核心字段contract_no、demand_id、quote_id、owner_id、company_id、total_price、start_date、end_date、status、create_time。從這張表開始業(yè)務(wù)已經(jīng)從信息撮合進入履約管理。contract_no可以用時間戳加隨機數(shù)生成答辯時也能說這是業(yè)務(wù)編號的規(guī)范做法。3.3 輔助鏈路施工進度、材料、驗收、評價第三組是輔助鏈路t_progress、t_material、t_acceptance、t_comment。t_progress用于裝修公司按階段上報施工進度。字段contract_id、stage、description、progress_percent、operator_id、create_time。其中stage可以約定為字符串比如拆改水電泥瓦木工油漆安裝竣工方便前端做時間線展示。一張合同下會有多條進度記錄所以是一對多關(guān)系。t_material是材料清單表屬于錦上添花的功能。字段contract_id、material_name、quantity、price、create_time。有了這張表這套系統(tǒng)就比只報文字進度的項目更有說服力可以做一個簡單的施工材料列表展示裝修過程的透明度。t_acceptance用于驗收。字段contract_id、result、comment、check_time、owner_id。result可以用0待驗收、1通過、2不通過。驗收完成之后t_contract.status也應(yīng)該跟著變化這個要在Service層里用事務(wù)控制。t_comment是業(yè)主對裝修公司服務(wù)的評價。字段contract_id、user_id、company_id、score、content、create_time。這里也可以做一個小功能當(dāng)新的評價產(chǎn)生時更新t_company.rating讓列表頁的公司評分跟著變化。3.4 幾個容易踩的坑金額精度、外鍵約束、狀態(tài)字段數(shù)據(jù)庫設(shè)計里有三個常見坑這個項目里特別容易觸發(fā)。第一金額字段不要用double。裝修預(yù)算、報價金額、合同金額、材料單價全部用decimal(10,2)Java實體里用BigDecimal接收。用double計算金額輕則顯示0.30000000000000004重則在寫入數(shù)據(jù)庫時出現(xiàn)精度誤差答辯時被問到會很難看。第二不要過度使用外鍵。畢設(shè)系統(tǒng)里的外鍵約束會造成兩個麻煩刪除順序必須嚴格測試數(shù)據(jù)初始化經(jīng)常失敗聯(lián)表查詢時MyBatis的關(guān)聯(lián)映射也變得復(fù)雜。我的建議是表結(jié)構(gòu)里保留邏輯外鍵字段比如demand_id、company_id但物理外鍵可以不建。保證查詢時能關(guān)聯(lián)出數(shù)據(jù)即可這件事可以在答辯時說成為了減少不必要的耦合使用應(yīng)用層事務(wù)保證一致性。第三狀態(tài)字段一定要加注釋。所有status字段建議在數(shù)據(jù)庫腳本里寫成COMMENT 0待接單 1已報價...這樣的形式。你過兩天回來看代碼或者指導(dǎo)老師看數(shù)據(jù)庫能一眼明白每個數(shù)字的含義。代碼里也建議定義一個常量類或者枚舉類避免在各種Mapper XML里寫裸數(shù)字。4. SSM工程落地項目結(jié)構(gòu)和核心代碼這樣寫才不亂4.1 推薦的分層結(jié)構(gòu)和Maven配置拿到源碼以后先看目錄結(jié)構(gòu)。一個規(guī)范的SSM項目通常是Maven構(gòu)建的JavaWeb工程推薦這樣分層src/main/java/com/example/decoration ├── controller # 控制器層 ├── service # 業(yè)務(wù)接口 ├── service/impl # 業(yè)務(wù)實現(xiàn) ├── mapper # MyBatis Mapper接口 ├── entity # 實體類 ├── common # 統(tǒng)一返回結(jié)果、常量、工具類 └── interceptor # 登錄攔截器、權(quán)限攔截器 src/main/resources ├── mapper # MyBatis SQL映射XML ├── spring # applicationContext.xml、spring-mvc.xml └── db.properties # 數(shù)據(jù)庫連接配置 src/main/webapp ├── WEB-INF/web.xml └── jsp # 頁面文件這套分層的核心思路是Controller只負責(zé)接收請求、調(diào)用Service、返回結(jié)果不直接操作數(shù)據(jù)庫Service負責(zé)業(yè)務(wù)邏輯和事務(wù)Mapper只負責(zé)SQL。很多同學(xué)寫畢設(shè)時喜歡在Controller里直接注入Mapper省事但答辯時老師問你這個Service層有什么意義就會很尷尬。既然是畢業(yè)設(shè)計一定要把Controller-Service-Mapper三層分清楚。Maven的pom.xml里核心依賴就是spring-webmvc、mybatis、mybatis-spring、mysql-connector-java、druid、jstl、servlet-api、jackson。注意兩個點一是servlet-api要標(biāo)scopeprovided/scope否則Tomcat里會沖突二是MySQL驅(qū)動版本要和自己本地的MySQL版本匹配5.7用5.1.49沒問題8.x就要用8.0.33。4.2 SSM常用注解和登錄攔截器實現(xiàn)這套系統(tǒng)里會用到不少SSM常用注解答辯前必須能說清楚Controller負責(zé)標(biāo)記控制器RequestMapping負責(zé)映射URLResponseBody負責(zé)把返回值轉(zhuǎn)成JSONService標(biāo)記業(yè)務(wù)層組件Autowired是依賴注入Transactional是聲明式事務(wù)。幾乎每個注解都是高頻考點。登錄攔截是本項目權(quán)限體系的核心。由于沒有引入Spring Security可以用SpringMVC的HandlerInterceptor來實現(xiàn)。public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); Object loginUser session.getAttribute(loginUser); if (loginUser null) { // 未登錄則跳轉(zhuǎn)到登錄頁也可以返回JSON response.sendRedirect(request.getContextPath() /login.jsp); return false; } return true; } }然后在spring-mvc.xml里注冊攔截器并排除登錄、注冊、靜態(tài)資源等路徑mvc:interceptors mvc:interceptor mvc:mapping path/**/ mvc:exclude-mapping path/login/ mvc:exclude-mapping path/register/ mvc:exclude-mapping path/static/**/ mvc:exclude-mapping path/css/**/ mvc:exclude-mapping path/js/**/ !-- 裝修需求列表和詳情可以允許游客查看 -- mvc:exclude-mapping path/demand/list/ mvc:exclude-mapping path/demand/detail/**/ bean classcom.example.decoration.interceptor.LoginInterceptor/ /mvc:interceptor /mvc:interceptors攔截器這部分建議一定自己寫一遍。很多網(wǎng)上源碼的權(quán)限控制就是頁面隱藏按鈕根本沒有后端攔截演示時繞開登錄直接訪問后端接口照樣能查數(shù)據(jù)。加上這個攔截器功能和代碼質(zhì)量都會提升一個檔次。4.3 業(yè)主發(fā)布需求三層代碼如何聯(lián)動以業(yè)主發(fā)布裝修需求這個核心動作為例把三層代碼完整走一遍。Controller層Controller RequestMapping(/demand) public class DemandController { Autowired private DemandService demandService; PostMapping(/publish) ResponseBody public Result publish(RequestBody Demand demand, HttpSession session) { User user (User) session.getAttribute(loginUser); if (user null || user.getRole() ! 1) { return Result.error(請使用業(yè)主賬號登錄); } demand.setUserId(user.getId()); demand.setStatus(0); demandService.publish(demand); return Result.success(); } }Service接口和實現(xiàn)類public interface DemandService { void publish(Demand demand); }Service public class DemandServiceImpl implements DemandService { Autowired private DemandMapper demandMapper; Override Transactional public void publish(Demand demand) { demand.setCreateTime(new Date()); demandMapper.insert(demand); } }MyBatis Mapper接口Repository public interface DemandMapper { int insert(Demand demand); }對應(yīng)的XMLinsert idinsert parameterTypecom.example.decoration.entity.Demand useGeneratedKeystrue keyPropertyid INSERT INTO t_demand (user_id, house_area, house_layout, decoration_style, budget, description, address, status, create_time) VALUES (#{userId}, #{houseArea}, #{houseLayout}, #{decorationStyle}, #{budget}, #{description}, #{address}, #{status}, #{createTime}) /insert注意幾個細節(jié)useGeneratedKeystrue和keyPropertyid保證了插入后能立刻拿到自增主鍵后續(xù)添加報價時可以直接使用ResponseBody配合統(tǒng)一的Result對象返回JSON比管理員返回字符串路徑更清晰。這套寫法學(xué)到之后在其他頁面也一樣用。4.4 裝修公司上報施工進度多條件更新和事務(wù)施工進度上報是一個典型的多條件更新場景。裝修公司可能只更新進度百分比也可能只更新描述文字甚至同時修改階段名稱。如果用固定SQL每次都要把所有字段傳進來很別扭。MyBatis的動態(tài)SQL正好解決這個問題。Controller層接收參數(shù)后組裝成一個Map或者直接使用Progress對象Service層調(diào)用Mapperupdate idupdateProgress parameterTypemap UPDATE t_progress set if teststage ! null and stage ! stage #{stage}, /if if testdescription ! null and description ! description #{description}, /if if testprogressPercent ! null progress_percent #{progressPercent}, /if /set WHERE id #{id} /update這里如果把更新進度和更新合同狀態(tài)放在同一個Service方法里建議加上Transactional。比如當(dāng)施工進度達到100%時自動把合同狀態(tài)改為待驗收。這個過程中有兩張表的數(shù)據(jù)要更新任何一步失敗都不能只更新一半否則數(shù)據(jù)就亂掉了。用Spring的聲明式事務(wù)只需要在方法上增加Transactional注解Spring會基于AOP幫你完成事務(wù)的開閉和回滾。這也是答辯時值得重點講的技術(shù)點在SSM里事務(wù)默認是針對運行時異常的受檢異常不會觸發(fā)回滾。所以Service里不要隨意catch掉所有異常否則事務(wù)會失效。5. 把源碼跑起來部署步驟和五個我實測踩過的坑5.1 前置環(huán)境與初始化在開始跑這套系統(tǒng)前建議準(zhǔn)備以下環(huán)境JDK 1.8、Maven 3.6、Tomcat 8.5或9.0、MySQL 5.7開發(fā)工具可以用IDEA或Eclipse。這些版本組合我實測下來最穩(wěn)定。具體步驟大概是這樣用IDEA將源碼作為Maven工程導(dǎo)入等待依賴下載完成。在本機MySQL里創(chuàng)建數(shù)據(jù)庫名稱建議用decoration_system編碼用utf8mb4。執(zhí)行源碼附帶的init.sql把建表和初始化數(shù)據(jù)一次導(dǎo)入。修改src/main/resources/db.properties里的數(shù)據(jù)庫地址、用戶名、密碼。配置Tomcat把項目deploy到Tomcat中啟動。瀏覽器訪問http://localhost:8080/看到登錄頁說明啟動成功。初始化數(shù)據(jù)里至少要有三個測試賬號管理員、業(yè)主、裝修公司。不然你在驗收一個功能時還要臨時注冊兩個角色非常麻煩。5.2 常見坑一數(shù)據(jù)庫版本和驅(qū)動不匹配這個坑出現(xiàn)頻率最高。學(xué)校機房很多是MySQL 5.5或5.7本地同學(xué)很多裝了MySQL 8.0。MySQL 8.0默認認證插件是caching_sha2_password老版本驅(qū)動連接時會報Public Key Retrieval is not allowed。解決辦法有兩個一是統(tǒng)一用MySQL 5.7數(shù)據(jù)庫腳本幾乎不用改二是如果必須用MySQL 8.0要在db.properties里加allowPublicKeyRetrievaltrueuseSSLfalse并把驅(qū)動換成com.mysql.cj.jdbc.Driver。我在源碼環(huán)境里默認寫的是MySQL 5.7配置如果你用8.0記得主動改。5.3 常見坑二Mapper XML沒有被打包進classesSSM項目里明明代碼看起來沒問題啟動后報Invalid bound statement (not found)大概率是Mapper XML沒有編譯到classes目錄下。Maven在打包時默認只把src/main/resources下的文件輸出到classpath如果你的XML放在src/main/java里需要通過pom配置resources才能打包。最簡單、也最建議的目錄結(jié)構(gòu)是Mapper接口放在src/main/java對應(yīng)的XML放在src/main/resources/mapper下兩者通過MyBatis的名稱空間和接口全限定名關(guān)聯(lián)。然后在spring-context.xml里的SqlSessionFactoryBean配置中設(shè)置mapperLocations指向classpath:mapper/*.xml。bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource/ property namemapperLocations valueclasspath:mapper/*.xml/ /bean5.4 常見坑三中文亂碼中文亂碼幾乎每個JavaWeb畢設(shè)項目都會遇到。亂碼原因一般有三個位置頁面本身編碼、請求編碼、數(shù)據(jù)庫連接編碼。JSP頁面用% page pageEncodingUTF-8 %。web.xml里配置CharacterEncodingFilter強制所有請求和響應(yīng)使用UTF-8。數(shù)據(jù)庫連接URL加characterEncodingutf8。數(shù)據(jù)庫表創(chuàng)建時統(tǒng)一用utf8mb4不要用默認的latin1。很多同學(xué)只改了頁面沒有配置CharacterEncodingFilter結(jié)果POST請求里帶中文就會亂。這個問題我排查過不少次配置一個全局過濾器基本能解決80%的亂碼問題filter filter-nameencodingFilter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping5.5 常見坑四靜態(tài)資源被DispatcherServlet攔截SpringMVC的DispatcherServlet如果配置成/會默認攔截所有請求包括css、js、圖片、html。如果不額外處理頁面就會變成裸體狀態(tài)沒有任何樣式。解決方式是在spring-mvc.xml里加入mvc:default-servlet-handler/ mvc:resources mapping/static/** location/static//然后把頁面的css和js統(tǒng)一放在webapp/static目錄下。這里要注意如果配置了自定義攔截器攔截/**靜態(tài)資源路徑一定要在exclude-mapping里排除否則登錄攔截器會把css請求也攔下來。5.6 常見坑五金額和日期字段的處理房屋裝修系統(tǒng)里到處是金額和時間處理不好就會出現(xiàn)兩類問題。一是金額精度問題前面已經(jīng)提到用BigDecimal。二是在JSON返回給前端時日期會變成一串時間戳非常不友好??梢栽赟pringMVC配置里加入JodaTime或者fastjson的序列化配置簡單一點的話可以在實體類的日期字段上加JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8)。這個細節(jié)屬于沒寫也不影響功能但寫了會讓代碼更完整的類型答辯時能給老師留下好印象。6. 答辯之前怎么把別人寫的源碼講成自己的亮點6.1 講清楚業(yè)務(wù)閉環(huán)畢業(yè)答辯時間通常很緊張老師不可能聽你逐個頁面念功能。建議用三分鐘時間只講一條主線業(yè)主發(fā)布需求裝修公司報價業(yè)主確認簽約裝修公司更新進度業(yè)主驗收評價。這條線每走到一個節(jié)點指出對應(yīng)的表、對應(yīng)的狀態(tài)變化、對應(yīng)的接口老師立刻就知道你是真懂這個項目。比如講到需求發(fā)布你可以說業(yè)主發(fā)布需求前端把表單數(shù)據(jù)提交給/demand/publishController層判斷登錄用戶角色后調(diào)用Service插入t_demand記錄初始狀態(tài)是0待接單。后面裝修公司登錄后查詢狀態(tài)為0的需求列表發(fā)起報價寫入t_quote。每個業(yè)務(wù)動作都直接驅(qū)動狀態(tài)變化這就是狀態(tài)流轉(zhuǎn)。6.2 四類高頻追問和參考答案畢業(yè)設(shè)計中老師非常喜歡圍繞框架、數(shù)據(jù)庫、并發(fā)、安全來提問。我總結(jié)過幾個高頻問題你可以照著準(zhǔn)備。問題核心作答思路SpringMVC的執(zhí)行流程用戶請求到達DispatcherServlet通過HandlerMapping找到對應(yīng)的Controller方法執(zhí)行后返回ModelAndView再經(jīng)過ViewResolver解析視圖。如果用了ResponseBody則直接由消息轉(zhuǎn)換器輸出JSONMyBatis和Hibernate的區(qū)別Hibernate是全自動ORM把Java對象和數(shù)據(jù)庫表映射后不需要寫SQLMyBatis是半自動ORMSQL由開發(fā)者自己控制和優(yōu)化。本項目多表聯(lián)查較多用MyBatis寫動態(tài)SQL更直觀項目里事務(wù)怎么控制在Spring配置文件中開啟tx:annotation-driven在Service方法上使用Transactional保證多個表操作要么同時成功要么同時回滾如何防止SQL注入MyBatis的#{}底層使用PreparedStatement預(yù)編譯傳入的參數(shù)被當(dāng)作參數(shù)值不會拼接進SQL如果用${}就要自己過濾。本項目統(tǒng)一使用#{}并在攔截器中校驗登錄狀態(tài)還有一個常被問到的為什么不用SpringBoot你只要從當(dāng)前學(xué)校課程體系以SSM為主SSM配置過程有助于理解框架運行機制兩個角度去回答基本不會卡殼。6.3 低成本二次開發(fā)建議源碼不是交完作業(yè)就結(jié)束了。如果你想在這個項目上加一些自己的東西以下三個方向成本都不高但是效果很明顯。一是加入ECharts統(tǒng)計報表。在后臺管理頁面統(tǒng)計不同裝修風(fēng)格的需求數(shù)量或者每月新增合同數(shù)量。這個只需要寫一個聚合查詢SQL返回一個包含名稱和數(shù)量的列表前端用ECharts畫柱狀圖或餅圖即可。它是典型的以項目數(shù)據(jù)為基礎(chǔ)的拓展功能論文里也好寫。二是增加Excel導(dǎo)出。合同列表加一個導(dǎo)出Excel按鈕后端用EasyPOI或POI把查詢結(jié)果寫入Excel前端點擊下載。這個功能能體現(xiàn)你對文件流和工具庫的掌握工作量不大但非常出效果。三是如果學(xué)校允許SpringBoot可以嘗試把這套系統(tǒng)改造成SpringBoot版本。把web.xml配置遷移成配置類把spring的XML配置改成注解你會發(fā)現(xiàn)框架之間遷移的邏輯是相通的這個改造過程能讓你對SSM的理解更深一層。最后再分享一個實際經(jīng)驗?zāi)玫竭@套SSM房屋裝修管理系統(tǒng)源碼之后我建議你第一周只干一件事把核心表之間的關(guān)系畫出來然后對著源碼把需求發(fā)布和報價確認這兩個接口的完整調(diào)用鏈走一遍。走通了后面的進度上報、驗收評價、后臺管理都是一樣的套路。自己動手改過、斷點打過的代碼答辯時才真正說得出口。