管理系統(tǒng)環(huán)境搭建與避坑指南)
簡(jiǎn)介這是一套基于Spring Boot、MyBatis、Spring MVC、Spring Security與Redis構(gòu)建的完整網(wǎng)站后臺(tái)管理系統(tǒng)源碼面向具備一定Java Web基礎(chǔ)、希望深入理解企業(yè)級(jí)開發(fā)技術(shù)棧協(xié)同方式的開發(fā)者與學(xué)習(xí)者。項(xiàng)目將持久層、控制層、安全認(rèn)證與緩存中間件整合在同一工程中可用于課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)參考或后臺(tái)管理系統(tǒng)的二次開發(fā)。壓縮包共326個(gè)文件約1.76MB其中95個(gè)Java源文件承載核心業(yè)務(wù)與配置邏輯45個(gè)JavaScript、33個(gè)HTML與19個(gè)CSS文件構(gòu)成前端交互與頁(yè)面樣式另有12個(gè)XML映射與配置文件、1個(gè)SQL腳本用于數(shù)據(jù)庫(kù)初始化以及gif、png、字體等靜態(tài)資源。已有958人學(xué)習(xí)下載。通過(guò)研讀源碼讀者可掌握Spring Security的登錄認(rèn)證與權(quán)限控制流程、MyBatis的SQL映射寫法、Redis緩存集成方式以及前后端資源在Spring Boot工程中的組織與配置思路適合作為技術(shù)進(jìn)階與項(xiàng)目實(shí)戰(zhàn)的參考素材。1. 從一臺(tái)干凈服務(wù)器開始Spring Boot MyBatis Spring MVC Spring Security Redis 后臺(tái)管理系統(tǒng)環(huán)境搭建很多人第一次拿到這套“Spring Boot MyBatis Spring MVC Spring Security Redis 完整網(wǎng)站后臺(tái)管理系統(tǒng)”源碼時(shí)第一反應(yīng)是直接雙擊 IDE 的 Run。結(jié)果大概率是數(shù)據(jù)庫(kù)連不上、Redis 拒絕連接、登錄頁(yè) 302 循環(huán)、控制臺(tái)一片紅。這套組合涉及五個(gè)核心組件版本錯(cuò)一個(gè)后面全是玄學(xué)問(wèn)題。我見過(guò)最典型的翻車現(xiàn)場(chǎng)是有人用 Spring Boot 3.x 去跑一份為 2.7.x 寫的 Security 配置WebSecurityConfigurerAdapter直接報(bào)紅整個(gè)認(rèn)證鏈起不來(lái)。所以這篇安裝筆記不聊架構(gòu)設(shè)計(jì)只解決一件事從零把這套環(huán)境裝到能登錄、能查數(shù)據(jù)、能跑通后臺(tái)首頁(yè)。適合手里已經(jīng)拿到源碼、但卡在環(huán)境配置上的開發(fā)者也適合想復(fù)盤一遍標(biāo)準(zhǔn)后臺(tái)環(huán)境搭建流程的熟手。2. 裝前定版本JDK、Maven、MySQL、Redis 四件套怎么選2.1 JDK 版本先看 Spring Boot 父工程再?zèng)Q定裝 8 還是 17這套系統(tǒng)能不能跑起來(lái)第一道門檻不是代碼是 JDK。Spring Boot 2.7.x 官方支持 JDK 8 到 JDK 17但 Spring Security 5.7 之后廢棄了WebSecurityConfigurerAdapter很多老教程里的配置類在 JDK 17 下編譯沒問(wèn)題運(yùn)行時(shí)會(huì)提示找不到適配器。我一般會(huì)先打開項(xiàng)目根目錄的pom.xml看parent里的spring-boot-starter-parent版本號(hào)。如果父工程是 2.x 系列穩(wěn)妥做法是裝 JDK 8 或 JDK 11。JDK 8 兼容性最好但如果你本地還要跑其他新項(xiàng)目JDK 11 是折中選擇。JDK 17 不是不能跑而是需要確認(rèn) Security 配置已經(jīng)改成SecurityFilterChainBean 的方式否則啟動(dòng)就報(bào)錯(cuò)。安裝 JDK 在 Linux 上常見做法是包管理器直接裝# Ubuntu/Debian 安裝 OpenJDK 11 sudo apt update sudo apt install -y openjdk-11-jdk # 驗(yàn)證版本 java -version javac -versionopenjdk-11-jdk會(huì)同時(shí)裝 JRE 和 JDKjavac能正常輸出版本號(hào)說(shuō)明編譯環(huán)境就緒。如果你用 CentOS把a(bǔ)pt換成yum包名換成java-11-openjdk-devel。裝完記得檢查JAVA_HOME# 查看 Java 安裝路徑 readlink -f $(which java) # 輸出類似 /usr/lib/jvm/java-11-openjdk-amd64/bin/java # 則 JAVA_HOME 應(yīng)設(shè)為 /usr/lib/jvm/java-11-openjdk-amd64JAVA_HOME不配置Maven 在某些系統(tǒng)上會(huì)找不到編譯器報(bào)No compiler is provided in this environment。這個(gè)坑我踩過(guò)不止一次尤其是在容器里跑構(gòu)建的時(shí)候。2.2 Maven 安裝與本地倉(cāng)庫(kù)路徑調(diào)整Maven 本身安裝不難難的是依賴下載慢和本地倉(cāng)庫(kù)爆盤。先裝# Ubuntu/Debian 安裝 Maven sudo apt install -y maven # 驗(yàn)證 mvn -vmvn -v會(huì)輸出 Maven 版本、Java 版本和系統(tǒng)信息。如果 Java 版本顯示不對(duì)說(shuō)明JAVA_HOME沒生效回頭檢查上一步。接下來(lái)改settings.xml位置在~/.m2/settings.xml沒有就新建。我一般會(huì)做兩件事?lián)Q國(guó)內(nèi)鏡像源、把本地倉(cāng)庫(kù)挪到大盤。settings localRepository/data/maven-repo/localRepository mirrors mirror idaliyun/id mirrorOfcentral/mirrorOf urlhttps://maven.aliyun.com/repository/public/url /mirror /mirrors /settingslocalRepository指向/data/maven-repo避免默認(rèn)~/.m2/repository把系統(tǒng)盤撐滿。mirrorOf寫central表示攔截中央倉(cāng)庫(kù)請(qǐng)求走阿里云公共倉(cāng)庫(kù)。這兩個(gè)參數(shù)改完mvn clean package的速度會(huì)有明顯差別。2.3 MySQL 8 安裝與建庫(kù)建用戶這套后臺(tái)管理系統(tǒng)通常自帶sql腳本里面包含建表語(yǔ)句和初始數(shù)據(jù)。MySQL 版本建議 8.0因?yàn)楹芏?Spring Boot 2.x 項(xiàng)目默認(rèn)驅(qū)動(dòng)是mysql-connector-java8.x連 5.7 雖然也能用但時(shí)區(qū)配置容易出問(wèn)題。# Ubuntu 安裝 MySQL 8 sudo apt install -y mysql-server # 啟動(dòng)并設(shè)置開機(jī)自啟 sudo systemctl start mysql sudo systemctl enable mysql # 安全初始化 sudo mysql_secure_installationmysql_secure_installation會(huì)引導(dǎo)你設(shè)置 root 密碼、移除匿名用戶、禁止 root 遠(yuǎn)程登錄。生產(chǎn)環(huán)境按提示走本地開發(fā)可以跳過(guò)部分選項(xiàng)。裝完后登錄建庫(kù)-- 創(chuàng)建數(shù)據(jù)庫(kù)字符集用 utf8mb4 CREATE DATABASE admin_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 創(chuàng)建專用用戶避免直接用 root CREATE USER admin_userlocalhost IDENTIFIED BY YourStrongPassword; -- 授權(quán) GRANT ALL PRIVILEGES ON admin_system.* TO admin_userlocalhost; FLUSH PRIVILEGES;字符集必須用utf8mb4否則后臺(tái)菜單里的中文、emoji 或者特殊符號(hào)會(huì)變成問(wèn)號(hào)。utf8mb4_general_ci是通用排序規(guī)則兼容性比utf8mb4_unicode_ci更穩(wěn)。建完庫(kù)再導(dǎo)入項(xiàng)目自帶的sql文件mysql -u admin_user -p admin_system /path/to/init.sql導(dǎo)入時(shí)如果報(bào)Unknown command \多半是sql文件里有反斜杠轉(zhuǎn)義用--default-character-setutf8mb4再試一次。2.4 Redis 安裝與密碼配置Redis 在這套系統(tǒng)里通常承擔(dān)驗(yàn)證碼存儲(chǔ)、登錄 Token 緩存、菜單權(quán)限緩存。裝 Redis 比 MySQL 簡(jiǎn)單# Ubuntu 安裝 Redis sudo apt install -y redis-server # 啟動(dòng) sudo systemctl start redis-server sudo systemctl enable redis-server # 測(cè)試連接 redis-cli ping返回PONG說(shuō)明服務(wù)正常。但默認(rèn)配置沒有密碼Spring Boot 連接時(shí)會(huì)報(bào)NOAUTH Authentication required或者直接連上但生產(chǎn)環(huán)境不安全。我一般會(huì)改/etc/redis/redis.conf# 設(shè)置訪問(wèn)密碼 requirepass YourRedisPassword # 綁定本地回環(huán)禁止外部訪問(wèn) bind 127.0.0.1 # 保護(hù)模式開啟 protected-mode yes改完重啟sudo systemctl restart redis-server redis-cli -a YourRedisPassword pingrequirepass設(shè)置密碼后redis-cli需要-a參數(shù)才能操作。bind 127.0.0.1確保只有本機(jī)能連避免暴露到公網(wǎng)。這兩項(xiàng)配完Spring Boot 的application.yml里也要同步改spring: redis: host: 127.0.0.1 port: 6379 password: YourRedisPassword database: 0database: 0是默認(rèn)庫(kù)如果項(xiàng)目里用了其他庫(kù)編號(hào)按實(shí)際改。密碼兩邊必須一致否則啟動(dòng)時(shí)RedisConnectionFailureException直接拋出來(lái)。3. 導(dǎo)入項(xiàng)目與配置從 pom.xml 到 application.yml 的逐項(xiàng)核對(duì)3.1 用 IDE 導(dǎo)入 Maven 項(xiàng)目并解決依賴沖突源碼拿到手第一步是導(dǎo)入 IDE。IntelliJ IDEA 選Open指向項(xiàng)目根目錄的pom.xml等 Maven 自動(dòng)下載依賴。如果右下角彈出Maven projects need to be imported點(diǎn)Import Changes。依賴下載完后常見問(wèn)題是spring-boot-starter-security和spring-boot-starter-web版本不一致。檢查pom.xml里有沒有顯式指定版本號(hào)如果有確認(rèn)和父工程版本匹配。我一般會(huì)跑一遍mvn dependency:tree -Dincludesorg.springframework.security輸出里如果出現(xiàn)多個(gè)不同版本的spring-security-core說(shuō)明有傳遞依賴沖突。解決辦法是在pom.xml里用dependencyManagement鎖定版本或者直接排除沖突依賴。另一個(gè)高頻問(wèn)題是 Lombok 插件沒裝。項(xiàng)目里大量用Data、Slf4jIDE 不裝 Lombok 插件代碼全是紅。IDEA 在Settings - Plugins搜 Lombok 安裝重啟后開啟Annotation Processors。3.2 application.yml 關(guān)鍵參數(shù)逐項(xiàng)說(shuō)明application.yml是這套系統(tǒng)能不能連上數(shù)據(jù)庫(kù)和 Redis 的關(guān)鍵。我一般按下面順序核對(duì)server: port: 8080 servlet: context-path: /admin spring: datasource: url: jdbc:mysql://127.0.0.1:3306/admin_system?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/ShanghaiuseSSLfalse username: admin_user password: YourStrongPassword driver-class-name: com.mysql.cj.jdbc.Driver redis: host: 127.0.0.1 port: 6379 password: YourRedisPassword database: 0 timeout: 5000 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.admin.entity configuration: map-underscore-to-camel-case: trueserver.servlet.context-path是后臺(tái)訪問(wèn)前綴如果項(xiàng)目里寫的是/admin訪問(wèn)地址就是http://localhost:8080/admin。datasource.url里的serverTimezoneAsia/Shanghai必須加MySQL 8 不加時(shí)區(qū)會(huì)報(bào)The server time zone value UTC is unrecognized。useSSLfalse本地開發(fā)關(guān)掉生產(chǎn)環(huán)境按需開啟。mybatis.mapper-locations指向 XML 映射文件位置type-aliases-package是實(shí)體類包名map-underscore-to-camel-case開啟后數(shù)據(jù)庫(kù)的user_name會(huì)自動(dòng)映射到 Java 的userName。這三個(gè)參數(shù)錯(cuò)一個(gè)查詢結(jié)果就是空或者報(bào)Invalid bound statement。3.3 Spring Security 配置類適配與放行規(guī)則Spring Security 是這套系統(tǒng)里最容易翻車的部分。如果項(xiàng)目用的是 Spring Boot 2.7 以上WebSecurityConfigurerAdapter已經(jīng)廢棄需要改成 Bean 方式Configuration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers(/login, /css/**, /js/**, /captcha).permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage(/login) .defaultSuccessUrl(/index) .permitAll() .and() .logout() .logoutUrl(/logout) .logoutSuccessUrl(/login) .and() .csrf().disable(); return http.build(); } }antMatchers里放行登錄頁(yè)、靜態(tài)資源、驗(yàn)證碼接口anyRequest().authenticated()表示其他全部需要認(rèn)證。formLogin指定自定義登錄頁(yè)和成功跳轉(zhuǎn)地址。csrf().disable()在前后端分離或者純后臺(tái)場(chǎng)景下常見做法是關(guān)掉否則 POST 請(qǐng)求會(huì)被攔截。如果項(xiàng)目里還是舊版WebSecurityConfigurerAdapter而你的 Spring Boot 是 2.7.x啟動(dòng)會(huì)報(bào)NoClassDefFoundError。解決辦法要么降 Spring Boot 版本到 2.6.x要么按上面改成 Bean 方式。我一般選后者因?yàn)樾掳姹景踩a(bǔ)丁更全。4. 避坑與排查啟動(dòng)失敗、登錄循環(huán)、Redis 超時(shí)的常見問(wèn)題4.1 啟動(dòng)報(bào)數(shù)據(jù)庫(kù)連接失敗先看驅(qū)動(dòng)再看時(shí)區(qū)現(xiàn)象啟動(dòng)時(shí)拋Cannot load driver class: com.mysql.cj.jdbc.Driver或者Communications link failure。原因第一種是pom.xml里沒加 MySQL 驅(qū)動(dòng)依賴或者驅(qū)動(dòng)版本和 MySQL 版本不匹配。第二種是 MySQL 沒啟動(dòng)或者url里的端口、庫(kù)名寫錯(cuò)。解決先確認(rèn)pom.xml有mysql-connector-java依賴版本用 8.0.x。然后systemctl status mysql看服務(wù)狀態(tài)mysql -u admin_user -p手動(dòng)登錄測(cè)試。如果報(bào)時(shí)區(qū)錯(cuò)誤在url末尾加serverTimezoneAsia/Shanghai。4.2 登錄頁(yè) 302 循環(huán)Security 放行規(guī)則寫錯(cuò)現(xiàn)象訪問(wèn)登錄頁(yè)瀏覽器不斷跳轉(zhuǎn)最終提示ERR_TOO_MANY_REDIRECTS。原因antMatchers里沒有放行登錄頁(yè)本身或者loginPage路徑和實(shí)際 Controller 映射不一致。Security 攔截了/login又跳轉(zhuǎn)到/login形成死循環(huán)。解決確認(rèn)antMatchers(/login).permitAll()存在且formLogin().loginPage(/login)的路徑和 Controller 里GetMapping(/login)完全一致。如果登錄頁(yè)在templates下還需要模板引擎依賴否則返回 404 也會(huì)觸發(fā)循環(huán)。4.3 Redis 連接超時(shí)密碼、綁定地址、保護(hù)模式三查現(xiàn)象啟動(dòng)時(shí)報(bào)RedisConnectionFailureException: Unable to connect to Redis。原因application.yml里的密碼和redis.conf不一致或者 Redis 綁定了127.0.0.1但項(xiàng)目連的是其他 IP或者保護(hù)模式開啟且沒有密碼。解決redis-cli -a 密碼 ping手動(dòng)測(cè)試。如果手動(dòng)能通檢查application.yml的host、port、password三項(xiàng)。如果手動(dòng)不通看redis.conf的bind和requirepass改完重啟 Redis。4.4 MyBatis 報(bào) Invalid bound statementmapper 路徑和包名對(duì)不上現(xiàn)象查詢時(shí)報(bào)org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)。原因mapper-locations配置的路徑下沒有對(duì)應(yīng)的 XML 文件或者 XML 里的namespace和 Mapper 接口全限定名不一致。解決檢查target/classes/mapper/目錄下有沒有 XML 文件。如果沒有說(shuō)明 Maven 沒把resources下的 XML 打包進(jìn)去需要在pom.xml的build里加resources resource directorysrc/main/resources/directory includes include**/*.xml/include /includes /resource /resources然后確認(rèn) XML 的namespace寫的是 Mapper 接口的完整包名加類名。4.5 靜態(tài)資源 404Security 攔截了 css/js現(xiàn)象登錄頁(yè)樣式全丟控制臺(tái)報(bào)GET /css/login.css 404。原因Security 默認(rèn)攔截所有請(qǐng)求靜態(tài)資源沒有放行。解決在antMatchers里加/css/**、/js/**、/images/**、/fonts/**。如果用了 WebJars還要加/webjars/**。放行后重啟樣式就能正常加載。5. 裝完怎么驗(yàn)證從登錄到數(shù)據(jù)查詢的完整走查環(huán)境裝完別急著寫業(yè)務(wù)。我一般會(huì)按下面順序走一遍確認(rèn)每個(gè)組件都真正通了。第一步確認(rèn)端口監(jiān)聽。ss -tlnp | grep -E 8080|3306|6379三個(gè)端口都應(yīng)該有進(jìn)程監(jiān)聽。8080 是 Spring Boot3306 是 MySQL6379 是 Redis。少一個(gè)就回頭查對(duì)應(yīng)服務(wù)。第二步訪問(wèn)登錄頁(yè)。瀏覽器打開http://localhost:8080/admin/login如果能看到登錄表單說(shuō)明 Spring MVC 和 Security 的放行規(guī)則生效。如果頁(yè)面樣式正常說(shuō)明靜態(tài)資源放行也沒問(wèn)題。第三步用初始賬號(hào)登錄。項(xiàng)目sql腳本里通常有一個(gè)sys_user表里面存了管理員賬號(hào)。常見做法是admin/123456但具體看init.sql的插入語(yǔ)句。登錄成功后應(yīng)該跳轉(zhuǎn)到后臺(tái)首頁(yè)左側(cè)菜單能正常展開。第四步驗(yàn)證 Redis 緩存。登錄后執(zhí)行redis-cli -a 密碼 keys *應(yīng)該能看到類似login:token:xxx或者captcha:xxx的鍵。如果沒有說(shuō)明 Redis 配置沒生效回頭檢查application.yml和redis.conf。第五步驗(yàn)證數(shù)據(jù)庫(kù)查詢。點(diǎn)開用戶管理或者菜單管理看列表能不能加載。如果列表為空但數(shù)據(jù)庫(kù)里有數(shù)據(jù)檢查 MyBatis 的mapper-locations和map-underscore-to-camel-case。如果報(bào)Invalid bound statement按 4.4 排查。第六步驗(yàn)證權(quán)限控制。用不同角色的賬號(hào)登錄看菜單和按鈕是否按權(quán)限顯示。Spring Security 的PreAuthorize注解需要開啟EnableGlobalMethodSecurity(prePostEnabled true)否則注解不生效。下面這張表是我每次裝完都會(huì)核對(duì)的檢查項(xiàng)檢查項(xiàng)預(yù)期結(jié)果失敗時(shí)看哪里JDK 版本java -version與 pom 匹配JAVA_HOME、pom parentMaven 依賴mvn clean package成功settings.xml、鏡像源MySQL 連接mysql -u admin_user -p能登錄服務(wù)狀態(tài)、url、時(shí)區(qū)Redis 連接redis-cli -a 密碼 ping返回 PONGrequirepass、bind登錄頁(yè)瀏覽器能打開且樣式正常Security 放行規(guī)則登錄跳轉(zhuǎn)成功進(jìn)入后臺(tái)首頁(yè)formLogin 配置數(shù)據(jù)查詢列表有數(shù)據(jù)mapper-locations、namespace權(quán)限控制不同角色菜單不同EnableGlobalMethodSecurity最后一步我會(huì)把a(bǔ)pplication.yml里的密碼換成環(huán)境變量避免提交到代碼倉(cāng)庫(kù)。常見做法是用${DB_PASSWORD}占位啟動(dòng)時(shí)通過(guò)-DDB_PASSWORDxxx傳入。這樣本地能跑線上也不會(huì)泄露。從那以后我每次裝這套環(huán)境都會(huì)先跑一遍mvn clean package -DskipTests確認(rèn)編譯通過(guò)再啟動(dòng)。因?yàn)楹芏嗯渲脝?wèn)題在編譯階段就能暴露等到運(yùn)行時(shí)才查成本高得多。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取