Java 面試框架篇:SSM 框架高頻面試題(含參考答案)

SSM(Spring+SpringMVC+MyBatis)是 Java 後端面試的核心考點,面試官通常從 “框架定位、核心原理、實戰問題、版本兼容” 四個層面提問。以下整理高頻面試題,結合你之前關注的 jar 包配置、分頁、測試等實戰場景,提供條理清晰的參考答案。

一、基礎理論類:框架定位與核心概念

1. 請簡述 SSM 框架的組成及各組件的核心作用?

參考答案

SSM 由 Spring、SpringMVC、MyBatis 三個框架組成,分工明確:

  • Spring:核心是 “容器 + 增強”,負責管理 Bean 的生命週期(IOC),通過 AOP 實現事務、日誌等橫切邏輯,同時作為 “粘合劑” 整合 SpringMVC 與 MyBatis;
  • SpringMVC:專注 Web 層,基於 “DispatcherServlet 前端控制器” 模式,負責請求接收、參數綁定、視圖渲染,核心是解耦請求分發與業務邏輯;
  • MyBatis:輕量級持久層框架,通過 “Mapper 接口 + XML 映射” 實現 SQL 與代碼分離,支持數據自動映射,簡化 JDBC 冗餘代碼。

三者協作邏輯:前端請求→SpringMVC 接收→調用 Spring 管理的 Service→Service 調用 MyBatis 的 Mapper→數據庫交互→返回結果。

2. Spring 的 IOC 和 AOP 分別是什麼?在 SSM 中有哪些具體應用?

參考答案

  • IOC(控制反轉):將對象的創建、組裝權從代碼轉移到 Spring 容器,通過註解(@Autowired)或 XML 配置實現依賴注入,避免硬編碼耦合。

SSM 應用:Service 依賴 Mapper、Controller 依賴 Service 時,無需手動new對象,由 Spring 自動注入(如@Autowired private UserService userService);

  • AOP(面向切面編程):基於動態代理,將日誌、事務等橫切邏輯從業務代碼中剝離,通過 “切入點 + 通知” 實現增強。

SSM 應用:Service 層的@Transactional註解(Spring 通過 AOP 自動開啓 / 提交 / 回滾事務)、全局異常處理(通過@Around攔截 Controller 異常)。

3. MyBatis 的核心組件有哪些?Mapper 接口為什麼不需要實現類?

參考答案

MyBatis 核心組件包括:SqlSessionFactory(創建 SqlSession 的工廠)、SqlSession(數據庫會話,執行 SQL)、Mapper接口(定義 SQL 方法)、Mapper XML(編寫 SQL)。

Mapper 接口無需實現類:MyBatis 通過 “動態代理” 技術,在運行時根據 Mapper 接口和 XML 中的 SQL,自動生成接口的代理對象(由SqlSession.getMapper(UserMapper.class)獲取)。代理對象會將接口方法與 XML 中的 SQL 綁定,調用接口方法時實際執行對應的 SQL,從而省略手動實現類。

二、核心原理類:框架運行機制

1. SpringMVC 的請求處理流程是怎樣的?(高頻面試題)

參考答案

SpringMVC 以DispatcherServlet為核心,流程分為 7 步:

  1. 前端發送請求(如/user/get),請求被DispatcherServlet接收;
  2. DispatcherServlet調用HandlerMapping(處理器映射器),根據 URL 匹配對應的Handler(即 Controller 方法);
  3. HandlerMapping返回HandlerExecutionChain(包含 Handler 和攔截器)給DispatcherServlet;
  4. DispatcherServlet調用HandlerAdapter(處理器適配器),適配 Handler 的參數(如將 URL 參數轉為 int 類型);
  5. HandlerAdapter執行 Handler(Controller 方法),調用 Service 層邏輯,返回ModelAndView(模型數據 + 視圖名);
  6. DispatcherServlet調用ViewResolver(視圖解析器),將邏輯視圖名(如userDetail)解析為實際視圖路徑(如/WEB-INF/views/userDetail.jsp);
  7. ViewResolver返回View對象,DispatcherServlet渲染視圖(將模型數據填充到視圖),最終返回給前端。

2. Spring 事務的傳播機制有哪些?在 SSM 中如何配置事務?

參考答案

Spring 事務傳播機制定義了 “多個事務方法嵌套調用時,事務如何傳遞”,核心傳播行為包括:

  • REQUIRED(默認):若當前有事務則加入,無則新建(如 Service 的addUser調用logService.addLog,兩者共用同一事務);
  • REQUIRES_NEW:無論當前是否有事務,都新建事務(如轉賬時記錄日誌,日誌事務獨立,轉賬失敗不影響日誌);
  • SUPPORTS:若當前有事務則加入,無則以非事務方式執行;
  • NOT_SUPPORTED:以非事務方式執行,若當前有事務則暫停。

SSM 中配置事務:有兩種方式:

  1. 註解方式(推薦):在 spring-mybatis.xml 中開啓事務註解驅動(<tx:annotation-driven transaction-manager="transactionManager"/>),然後在 Service 方法上添加@Transactional(propagation = Propagation.REQUIRED);
  2. XML 方式:通過<tx:advice>定義事務通知,<aop:config>配置切入點(如匹配 Service 層所有方法),將通知與切入點關聯。

3. MyBatis 的一級緩存和二級緩存有什麼區別?如何開啓二級緩存?

參考答案

對比維度

一級緩存

二級緩存

作用範圍

SqlSession(會話級別)

Mapper 接口(全局級別)

生命週期

隨 SqlSession 創建 / 關閉

隨 SqlSessionFactory 存在

數據共享

僅當前 SqlSession 可見

所有 SqlSession 共享

默認狀態

自動開啓

需手動開啓

開啓二級緩存

  1. 在 MyBatis 全局配置文件(mybatis-config.xml)中開啓緩存(默認開啓,可省略):<settings><setting name="cacheEnabled" value="true"/></settings>;
  2. 在需要開啓二級緩存的 Mapper XML 中添加<cache/>標籤(如 UserMapper.xml);
  3. 確保 POJO 類實現Serializable接口(二級緩存需序列化存儲數據)。

三、實戰問題類:項目開發與問題排查

1. SSM 框架中如何實現分頁查詢?PageHelper 的原理是什麼?(結合你之前關注的分頁場景)

參考答案

SSM 中常用PageHelper插件實現分頁,步驟如下:

  1. 引入 PageHelper 依賴(Maven):com.github.pagehelper:pagehelper:5.1.10;
  2. 在 mybatis-config.xml 中配置插件:指定數據庫方言(如 MySQL)、啓用合理化分頁;
  3. Service 層調用PageHelper.startPage(pageNum, pageSize)啓動分頁,後續第一個 Mapper 查詢會自動添加LIMIT語句;
  4. 將查詢結果封裝為PageInfo對象(含總條數、總頁數、當前頁數據),返回給 Controller。

PageHelper 原理:基於 MyBatis 的Interceptor(插件)機制,攔截Executor.query()方法(執行 SQL 的核心方法)。當調用PageHelper.startPage()時,會將分頁參數(pageNum、pageSize)存入ThreadLocal(線程局部變量,確保線程安全);攔截 SQL 時,從ThreadLocal中獲取分頁參數,根據數據庫方言生成對應的分頁 SQL(如 MySQL 加LIMIT,Oracle 加ROWNUM),最後清空ThreadLocal中的參數。

2. SSM 項目中遇到 SQL 注入問題,如何解決?(安全問題高頻考點)

參考答案

SQL 注入是因 “用户輸入直接拼接 SQL” 導致,MyBatis 中可通過以下方式預防:

  1. 使用 #{} 佔位符:MyBatis 會將#{} 解析為?,通過 PreparedStatement 預編譯 SQL,自動對參數轉義(如用户輸入'or 1=1'會被當作字符串處理),這是最推薦的方式;

❌ 錯誤:SELECT * FROM tb_user WHERE username = '${username}'(${} 直接拼接 SQL,存在注入風險);

✅ 正確:SELECT * FROM tb_user WHERE username = #{username};

  1. 限制參數類型:如 Mapper 接口方法參數指定為int id,避免傳入字符串導致 SQL 變形;
  2. 使用 MyBatis 的foreach標籤:批量操作(如批量刪除)時,用foreach生成參數,避免手動拼接id in (1,2,3);
  3. 開啓 MyBatis 的日誌:通過日誌監控 SQL 執行,及時發現異常拼接的 SQL。

3. SSM 框架中,Controller 如何接收前端參數?常見的參數綁定註解有哪些?

參考答案

SpringMVC 提供多種參數綁定方式,適應不同前端傳參場景:

  1. URL 路徑參數:用@PathVariable接收(如/user/get/{id}):
@GetMapping("/user/get/{id}")public User getUser(@PathVariable("id") Integer id) { ... }
  1. URL 查詢參數:用@RequestParam接收(如/user/list?pageNum=1&pageSize=10),支持默認值:
@GetMapping("/user/list")public PageInfo<User> getUserList(@RequestParam(defaultValue = "1") int pageNum) { ... }
  1. JSON 請求體:用@RequestBody接收前端傳遞的 JSON 數據(需引入 Jackson 依賴,如com.fasterxml.jackson.core:jackson-databind:2.9.8):
@PostMapping("/user/add")public void addUser(@RequestBody User user) { ... }
  1. 表單參數:直接用 POJO 接收(表單字段名與 POJO 屬性名一致):
@PostMapping("/user/update")public void updateUser(User user) { ... } // 表單字段username對應user.getUsername()

四、對比選型與版本類:框架差異與兼容

1. SSM 和 SpringBoot 有什麼區別?為什麼現在更多項目用 SpringBoot?(結合你之前關注的框架對比)

參考答案

SSM 與 SpringBoot 的核心區別在於 “配置複雜度” 和 “開發效率”:

對比維度

SSM 框架

SpringBoot 框架

配置方式

手動編寫 XML(如 spring-mybatis.xml、spring-mvc.xml)

自動配置 + application.yml(約定大於配置)

依賴管理

手動協調版本(如 Spring 與 MyBatis 版本匹配)

Starter 依賴(如spring-boot-starter-web,自動管理版本)

服務器

依賴外部 Tomcat,需手動部署 WAR 包

內置 Tomcat,支持 JAR 包直接運行(java -jar)

開發效率

框架搭建耗時(1-2 小時)

一鍵生成項目(Spring Initializr),10 分鐘啓動

SpringBoot 更流行的原因

  • 解決 SSM “配置繁瑣” 的痛點,自動整合框架(如引入mybatis-spring-boot-starter即自動配置 SqlSessionFactory);
  • 內置服務器,無需部署,適合微服務架構(單個服務獨立運行);
  • 支持熱部署(spring-boot-devtools)、監控(actuator)等增強功能,提升開發與運維效率。

2. SSM 框架中,Spring、SpringMVC、MyBatis 的版本如何選擇?若出現版本衝突該如何解決?(結合你之前關注的 jar 包配置)

參考答案

版本選擇原則:確保三者兼容性,推薦穩定組合:

  • Spring 版本:4.3.x(如 4.3.20.RELEASE),穩定且兼容 MyBatis 3.4.x、SpringMVC 4.3.x;
  • SpringMVC 版本:必須與 Spring 核心版本一致(避免版本拆分導致的類衝突,如 Spring 4.3.20 對應 SpringMVC 4.3.20);
  • MyBatis 版本:3.4.x(如 3.4.6),兼容 Spring 4.x,支持 PageHelper 5.x;
  • 數據庫驅動:MySQL 5.x 用mysql-connector-java:5.1.47,MySQL 8.x 用8.0.28(需加serverTimezone=UTC參數)。

版本衝突解決方法

  1. 查看錯誤日誌:若出現NoSuchMethodError或ClassNotFoundException,優先檢查衝突類的來源(如通過 Maven 的mvn dependency:tree命令查看依賴樹);
  2. 排除衝突依賴:在 pom.xml 中用<exclusion>排除衝突的 jar 包(如 SpringMVC 依賴的 Spring 核心包與手動引入的版本衝突,可排除手動引入的);
  3. 統一版本管理:在 pom.xml 的<properties>中定義版本變量(如${spring.version}),確保所有 Spring 相關依賴使用同一版本。

3. SSM 和 SpringCloud 的關係是什麼?兩者能否一起使用?

參考答案

SSM 與 SpringCloud 的定位不同,是 “基礎框架” 與 “微服務治理框架” 的關係:

  • SSM:專注於 “單體項目的分層開發”,解決 Web 層、業務層、持久層的協作問題;
  • SpringCloud:基於 SpringBoot,專注於 “微服務架構的治理”,解決服務註冊發現、負載均衡、熔斷降級等分佈式問題(如 Eureka、Gateway)。

兩者可一起使用:實際項目中,通常將 SSM 的 “業務邏輯” 遷移到 SpringBoot 項目中(用 SpringBoot 簡化 SSM 配置),再將多個 SpringBoot 項目組成微服務集羣,用 SpringCloud 進行治理。例如:“用户服務”(SpringBoot+MyBatis)、“訂單服務”(SpringBoot+MyBatis),通過 SpringCloud 的 Eureka 註冊服務,Gateway 作為統一入口。

五、面試加分項:實戰優化與最佳實踐

1. SSM 項目中,如何優化 MyBatis 的性能?

參考答案

  1. SQL 優化:避免全表掃描(給查詢字段建索引)、減少SELECT *(只查需要的字段)、用LEFT JOIN替代子查詢;
  2. 緩存優化:開啓 MyBatis 二級緩存(減少數據庫查詢次數),結合 Redis 實現分佈式緩存(解決多節點緩存不一致);
  3. 批量操作優化:用 MyBatis 的foreach標籤實現批量插入 / 更新(如insert into tb_user values (#{item.username}, ...)),避免循環調用單條插入;
  4. 連接池優化:使用 Druid 連接池,配置合理的連接數(initialSize=5、maxActive=20),避免連接泄漏;
  5. 延遲加載:開啓 MyBatis 延遲加載(<setting name="lazyLoadingEnabled" value="true"/>),避免關聯查詢時加載不必要的數據(如查詢用户時不默認加載訂單列表)。

2. SSM 框架中,如何實現全局異常處理?

參考答案

SpringMVC 提供@ControllerAdvice+@ExceptionHandler實現全局異常處理,無需在每個 Controller 中捕獲異常:

  1. 創建全局異常處理類:
@ControllerAdvice // 全局Controller增強public class GlobalExceptionHandler {    // 處理業務異常(自定義異常類)    @ExceptionHandler(BusinessException.class)    @ResponseBody    public Map<String, Object> handleBusinessException(BusinessException e) {        Map<String, Object> result = new HashMap<>();        result.put("code", e.getCode());        result.put("msg", e.getMessage());        return result;    }    // 處理系統異常(如NullPointerException)    @ExceptionHandler(Exception.class)    @ResponseBody    public Map<String, Object> handleSystemException(Exception e) {        Map<String, Object> result = new HashMap<>();        result.put("code", 500);        result.put("msg", "服務器異常:" + e.getMessage());        return result;    }}
  1. 自定義業務異常類(如BusinessException),包含錯誤碼和錯誤信息;
  2. 業務中拋出異常(如throw new BusinessException(400, "用户名已存在")),全局處理器會自動捕獲並返回統一格式的 JSON 結果。