- 臨近秋招,備戰暑期實習,祝大家每天進步億點點!Day20
- 每日10道題打卡,本篇總結 SSM 三大框架相關面試題~

1、什么是有狀態登錄和無狀態登錄?
內容參考自:有狀態登錄和無狀態登錄概念
- 有狀態登錄:
當客戶端第一次請求服務器時(請求登錄),服務器創建 Session ,然后將登錄用戶身份資訊保存到 Session 中,并將用戶身份資訊作為 “門卡”,回應回客戶端,客戶端將服務器回應的 “門卡” 資訊保存在本地 Cookie 中,
當下一次客戶端再次請求服務器時,這時候就直接將客戶端的 Cookie 中存放的 “門卡” 帶到服務器端,服務器端從 Session 中拿出資料和 “門卡” 進行對比,判斷是否可以同行,
-
無狀態登錄的缺點:
- 服務端保存大量用戶身份標識,增加服務端壓力,
- 客戶端請求依賴服務端,多次請求必須訪問同一臺服務器(如果是集群,相當于啟動了多個 Tomcat,這時候無法在多個 Tomcat 直接共享 Session 資料),
-
無狀態登錄:
服務器不保存任何客戶端用戶的登錄資訊!
客戶端的每次請求服務器必須自己具備身份資訊標識(jwt),服務器端通過身份資訊標識識別客戶端身份,
- 無狀態登錄的好處:
- 客戶端請求不依賴服務端的資訊,任何多次請求不需要必須訪問到同一臺服務器,
- 減小服務端存盤壓力,
如何實作無狀態登錄?
如圖所示:

- 當客戶端第一次請求服務時,服務端對用戶進行資訊認證(登錄),
- 認證通過,將用戶身份資訊(不包含密碼)進行加密形成
token,回傳給客戶端,作為登錄憑證, - 以后每次請求,客戶端都攜帶認證的
token, - 服務的對
token進行解密,判斷是否有效,
2、過濾器,攔截器,Aop區別?
非常詳細的參考文章:
- 過濾器 和 攔截器的 6個區別,別再傻傻分不清了
- 最詳細的講解過濾器,攔截器,AOP的區別
3、什么是SpringMvc,說一說它的幾個核心組成?
- ① 前端控制器(DispatcherServlet):主要用于接收客戶端發送的 HTTP 請求、回應結果給客戶端,
- ② 處理器映射器(HandlerMapping):根據請求的 URL 來定位到對應的處理器(Handler),
- ③ 處理器配接器(HandlerAdapter):在撰寫處理器(Handler)的時候要按照處理器配接器(HandlerAdapter) 要求的規則去撰寫,通過配接器可以正確的去執行 Handler,
- ④ 處理器(Handler):就是我們經常寫的 Controller 層代碼,例如:
UserController, - ⑤ 視圖決議器(ViewResolver):進行視圖的決議,將 ModelAndView 物件決議成真正的視圖(View)物件回傳給前端控制器,
- ⑥ 視圖(View):View 是一個介面, 它的實作類支持不同的視圖型別(JSP,FreeMarker,Thymleaf 等),
4、Springmvc執行流程?
- ① 首先,用戶發送 HTTP 請求給 SpringMVC 前端控制器 DispatcherServlet,
- ② DispatcherServlet 收到請求后,呼叫HandlerMapping 處理器映射器,根據請求 URL 去定位到具體的處理器 Handler,并將該處理器物件回傳給 DispatcherServlet ,
- ③ 接下來,DispatcherServlet 呼叫 HandlerAdapter 處理器配接器,通過處理器配接器呼叫對應的 Handler 處理器處理請求,并向前端控制器回傳一個 ModelAndView 物件,
- ④ 然后,DispatcherServlet 將 ModelAndView 物件交給 ViewResoler 視圖決議器去處理,并回傳指定的視圖 View 給前端控制器,
- ⑤ DispatcherServlet 對 View 進行渲染(即將模型資料填充至視圖中),View 是一個介面, 它的實作類支持不同的視圖型別(JSP,FreeMarker,Thymleaf 等),
- ⑥ DispatcherServlet 將頁面回應給用戶,
5、什么是MyBatis 一、二級快取?
擴展文章:SpringBoot整合Redis作為Mybatis二級快取
- 一級快取:作用域是 SqlSession,同一個 SqlSession 中執行相同的 SQL 查詢(相同的SQL和引數),第一次會去查詢資料庫并寫在快取中,第二次會直接從快取中取,
- 一級快取是基于 PerpetualCache 的 HashMap 本地快取,默認打開一級快取,
- 失效策略:當執行 SQL 時候兩次查詢中間發生了增刪改的操作,即
insert、update、delete等操作commit后會清空該 SqlSession 快取,
- 二級快取:作用域是 NameSpace 級別,多個 SqlSession 去操作同一個 NameSpace 下的 Mapper 檔案的 sql 陳述句,多個 SqlSession可以共用二級快取,如果兩個 Mapper 的 NameSpace 相同,(即使是兩個 Mapper,那么這兩個 Mapper 中執行 sql 查詢到的資料也將存在相同的二級快取區域中)
- 二級快取也是基于 PerpetualCache 的 HashMap 本地快取,可自定義存盤源,如 Ehcache/Redis等,默認是沒有開啟二級快取,
- 操作流程:第一次呼叫某個 NameSpace 下的 SQL 去查詢資訊,查詢到的資訊會存放該 Mapper對應的二級快取區域,第二次呼叫同個 NameSpace 下的 Mapper 映射檔案中的相同的 sql 去查詢資訊時,會去對應的二級快取內取結果,
- 失效策略:執行同個 NameSpace 下的 Mapepr 映射檔案中增刪改 sql,并執行了
commit操作,會清空該二級快取,
注意:實作二級快取的時候,MyBatis 建議回傳的 POJO 是可序列化的, 也就是建議實作 Serializable 介面,
如圖所示:

當 Mybatis 呼叫 Dao 層查詢資料庫時,先查詢二級快取,二級快取中無對應資料,再去查詢一級快取,一級快取中也沒有,最后去資料庫查找,
6、為什么說 Mybatis 是半自動ORM映射工具?它與全自動的區別在哪里?
ORM 是什么?
ORM(Object Relational Mapping),物件關系映射,是一種為了解決關系型資料庫資料與簡單 Java 物件(POJO)建里映射關系的技術,
為什么說 Mybatis 是半自動ORM映射工具?它與全自動的區別在哪里?
- 首先,像 Hibernate、JPA 這種屬于全自動 ORM 映射工具,使用 Hibernate 查詢關聯物件或者關聯集合物件時,可以根據物件關系模型直接獲取,所以它是全自動的,
- 而 Mybatis 在查詢關聯物件或關聯集合物件時,需要手動撰寫 sql 來完成,所以,稱之為半自動 ORM 映射工具,
- 換句話來解釋就是說 MyBatis 是 半自動 ORM 最主要的一個原因是,它需要在 XML 或者注解里通過手動或插件生成 SQL,才能完成 SQL 執行結果與物件映射系結,
7、能否簡單說下Mybatis加載的流程?
- MyBatis 是以一個 SqlSessionFactory 實體為核心,SqlSessionFactory 的實體可以通過 SqlSessionFactoryBuilder 獲得,
- SqlSessionFactoryBuilder 可以從 XML 組態檔或一個預先配置的 Configuration 實體來構建出 SqlSessionFactory 實體,
- SqlSessionFactory 實體工廠可以生產 SqlSession ,它里面提供了在資料庫執行 SQL 命令所需的所有方法,
具體流程:
① 加載組態檔:需要加載的組態檔包括全域組態檔(mybatis-config.xml)和 SQL(Mapper.xml) 映射檔案,其中全域組態檔配置了Mybatis 的運行環境資訊(資料源、事務等),SQL映射檔案中配置了與 SQL 執行相關的資訊,
② 創建會話工廠:MyBatis通過讀取組態檔的資訊來構造出會話工廠(SqlSessionFactory),即通過SqlSessionFactoryBuilder 構建 SqlSessionFactory,
③ 創建會話:擁有了會話工廠,MyBatis就可以通過它來創建會話物件(SqlSession),會話物件是一個介面,該介面中包含了對資料庫操作的增刪改查方法,
④ 創建執行器:因為會話物件本身不能直接操作資料庫,所以它使用了一個叫做資料庫執行器(Executor)的介面來幫它執行操作,
⑤ 封裝SQL物件:執行器(Executor)將待處理的SQL資訊封裝到一個物件中(MappedStatement),該物件包括SQL陳述句、輸入引數映射資訊(Java簡單型別、HashMap或POJO)和輸出結果映射資訊(Java簡單型別、HashMap 或 POJO),
⑥ 操作資料庫:擁有了執行器和SQL資訊封裝物件就使用它們訪問資料庫了,最后再回傳操作結果,結束流程,
8、什么是 Spring 三級快取?
所謂三級快取,其實就是org.springframework.beans.factory包下DefaultSingletonBeanRegistry類中的三個成員屬性:
// Spring一級快取:用來保存實體化、初始化都完成的物件
// Key:beanName
// Value: Bean實體
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// Spring二級快取:用來保存實體化完成,但是未初始化完成的物件
// Key:beanName
// Value: Bean實體
// 和一級快取一樣也是保存BeanName和創建bean實體之間的關系,
// 與singletonObjects不同之處在于,當一個單例bean被放在里面后,
// 那么bean還在創建程序中,就可以通過getBean方法獲取到了,其目的是用來回圈檢測參考!(后面會分析)
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
// Spring三級快取:用來保存一個物件工廠,提供一個匿名內部類,用于創建二級快取中的物件
// Key:beanName
// Value: Bean的工廠
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
如圖所示,除了三級快取是一個HashMap,其他兩個都是ConcurrentHashMap:

Spring之所以引入三級快取,目的就是為了解決回圈依賴問題!
除了上面三個Map集合,還有另一個集合這里也說一下:
// 用來保存當前所有已注冊的Bean
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
9、什么是 Spring回圈依賴問題?如何解決?
首先,Spring 解決回圈依賴有兩個前提條件:
- Setter方式注入造成的回圈依賴(構造器方式注入不可以)
- 必須是單例
本質上解決回圈依賴的問題就是依靠三級快取,通過三級快取提前拿到未初始化的物件,下面我們來看一個回圈依賴的例子:

A 物件的創建程序:
-
創建物件A,實體化的時候把A物件工廠放入三級快取

-
A 注入屬性時,發現依賴 B,轉而去實體化 B
-
同樣創建物件 B,注入屬性時發現依賴 A,一次從一級到三級快取查詢 A,從三級快取通過物件工廠拿到 A,把 A 放入二級快取,同時洗掉三級快取中的 A,此時,B 已經實體化并且初始化完成,把 B 放入一級快取,

-
接著繼續創建 A,順利從一級快取拿到實體化且初始化完成的 B 物件,A 物件創建也完成,洗掉二級快取中的 A,同時把 A 放入一級快取,
-
最后,一級快取中保存著實體化、初始化都完成的A、B 物件,

- 從上面5步驟的分析可以看出,三級快取解決回圈依賴是通過把實體化和初始化的流程分開了,所以如果都是用構造器的話,就沒法分離這個操作(因為構造器注入實體化和初始是一起進行的),因此構造器方式注入的話是無法解決回圈依賴問題的,
解決回圈依賴為什么必須要要三級快取?二級不行嗎?
答案:不可以!
使用三級快取而非二級快取并不是因為只有三級快取才能解決回圈參考問題,其實二級快取同樣也能很好解決回圈參考問題,
使用三級而非二級快取并非出于IOC的考慮,而是出于AOP的考慮,即若使用二級快取,在AOP情形下,往二級快取中放一個普通的Bean物件,BeanPostProcessor去生成代理物件之后,覆寫掉二級快取中的普通Bean物件,那么多執行緒環境下可能取到的物件就不一致了,
- 一句話總結就是,在 AOP 代理增強 Bean 后,會對早期物件造成覆寫,如果多執行緒情況下可能造成取到的物件不一致~
10、說說Spring 里用到了哪些設計模式?
單例模式:Spring 中的 Bean 默認情況下都是單例的,無需多說,工廠模式:工廠模式主要是通過 BeanFactory 和 ApplicationContext 來生產 Bean 物件,代理模式:最常見的 AOP 的實作方式就是通過代理來實作,Spring主要是使用 JDK 動態代理和 CGLIB 代理,- …
這里給大家推薦三篇關于上面三種設計模式的文章:
【Java實習生】面試常問設計模式——單例模式
【Java實習生】面試常問設計模式——工廠模式
【Java實習生】面試常問設計模式——代理模式
總結的面試題也挺費時間的,文章會不定時更新,有時候一天多更新幾篇,如果幫助您復習鞏固了知識點,還請三連支持一下,后續會億點點的更新!

為了幫助更多小白從零進階 Java 工程師,從CSDN官方那邊搞來了一套 《Java 工程師學習成長知識圖譜》,尺寸 870mm x 560mm,展開后有一張辦公桌大小,也可以折疊成一本書的尺寸,有興趣的小伙伴可以了解一下,當然,不管怎樣博主的文章一直都是免費的~

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/286946.html
標籤:java
