日分享開始啦,請大家多多指教~
本篇總結 SSM 三大框架相關面試題~
當客戶端第一次請求服務器時(請求登錄),服務器創建 Session ,然后將登錄用戶身份信息保存到 Session 中,并將用戶身份信息作為 “門卡”,響應回客戶端,客戶端將服務器響應的 “門卡” 信息保存在本地 Cookie 中。
當下一次客戶端再次請求服務器時,這時候就直接將客戶端的 Cookie 中存放的 “門卡” 帶到服務器端,服務器端從 Session 中拿出數據和 “門卡” 進行對比,判斷是否可以同行。
服務端保存大量用戶身份標識,增加服務端壓力。
客戶端請求依賴服務端,多次請求必須訪問同一臺服務器(如果是集群,相當于啟動了多個 Tomcat,這時候無法在多個 Tomcat 直接共享 Session 數據)。
服務器不保存任何客戶端用戶的登錄信息!
客戶端的每次請求服務器必須自己具備身份信息標識(jwt),服務器端通過身份信息標識識別客戶端身份。
客戶端請求不依賴服務端的信息,任何多次請求不需要必須訪問到同一臺服務器。
減小服務端存儲壓力。
如何實現無狀態登錄?
如圖所示:
過濾器和攔截器均體現了AOP的編程思想,都可以實現諸如日志記錄、登錄鑒權等功能,但二者的不同點也是比較多的。
1、實現原理不同
過濾器和攔截器 底層實現方式大不相同,過濾器是基于函數回調的,攔截器則是基于Java的反射機制(動態代理)實現的。
2、使用范圍不同
我們看到過濾器實現的是 javax.servlet.Filter 接口,而這個接口是在Servlet規范中定義的,也就是說過濾器Filter 的使用要依賴于Tomcat等容器,導致它只能在web程序中使用。
而攔截器(Interceptor) 它是一個Spring組件,并由Spring容器管理,并不依賴Tomcat等容器,是可以單獨使用的。不僅能應用在web程序中,也可以用于Application、Swing等程序中。
3、觸發時機不同
過濾器Filter是在請求進入容器后,但在進入servlet之前進行預處理,請求結束是在servlet處理完以后。
攔截器 Interceptor 是在請求進入servlet后,在進入Controller之前進行預處理的,Controller 中渲染了對應的視圖之后請求結束。
4、攔截的請求范圍不同
5、注入Bean情況不同
在實際的業務場景中,應用到過濾器或攔截器,為處理業務邏輯難免會引入一些service服務。
6、控制執行順序不同
實際開發過程中,會出現多個過濾器或攔截器同時存在的情況,不過,有時我們希望某個過濾器或攔截器能優先執行,就涉及到它們的執行順序。
① 前端控制器(DispatcherServlet):主要用于接收客戶端發送的 HTTP 請求、響應結果給客戶端。
② 處理器映射器(HandlerMapping):根據請求的 URL 來定位到對應的處理器(Handler)。
③ 處理器適配器(HandlerAdapter):在編寫處理器(Handler)的時候要按照處理器適配器(HandlerAdapter) 要求的規則去編寫,通過適配器可以正確地去執行 Handler。
④ 處理器(Handler):就是我們經常寫的 Controller 層代碼,例如:UserController。
⑤ 視圖解析器(ViewResolver):進行視圖的解析,將 ModelAndView 對象解析成真正的視圖(View)對象返回給前端控制器。
⑥ 視圖(View):View 是一個接口, 它的實現類支持不同的視圖類型(JSP,FreeMarker,Thymleaf 等)。
① 首先,用戶發送 HTTP 請求給 SpringMVC 前端控制器 DispatcherServlet。
② DispatcherServlet 收到請求后,調用HandlerMapping 處理器映射器,根據請求 URL 去定位到具體的處理器 Handler,并將該處理器對象返回給 DispatcherServlet 。
③ 接下來,DispatcherServlet 調用 HandlerAdapter 處理器適配器,通過處理器適配器調用對應的 Handler 處理器處理請求,并向前端控制器返回一個 ModelAndView 對象。
④ 然后,DispatcherServlet 將 ModelAndView 對象交給 ViewResoler 視圖解析器去處理,并返回指定的視圖 View 給前端控制器。
⑤ DispatcherServlet 對 View 進行渲染(即將模型數據填充至視圖中)。View 是一個接口, 它的實現類支持不同的視圖類型(JSP,FreeMarker,Thymleaf 等)。
⑥ DispatcherServlet 將頁面響應給用戶。
一級緩存:作用域是 SqlSession,同一個 SqlSession 中執行相同的 SQL 查詢(相同的SQL和參數),第一次會去查詢數據庫并寫在緩存中,第二次會直接從緩存中取。
二級緩存:作用域是 NameSpace 級別,多個 SqlSession 去操作同一個 NameSpace 下的 Mapper 文件的 sql 語句,多個 SqlSession可以共用二級緩存,如果兩個 Mapper 的 NameSpace 相同,(即使是兩個 Mapper,那么這兩個 Mapper 中執行 sql 查詢到的數據也將存在相同的二級緩存區域中)。
注意:實現二級緩存的時候,MyBatis 建議返回的 POJO 是可序列化的, 也就是建議實現 Serializable 接口。
如圖所示:
當 Mybatis 調用 Dao 層查詢數據庫時,先查詢二級緩存,二級緩存中無對應數據,再去查詢一級緩存,一級緩存中也沒有,最后去數據庫查找。
ORM 是什么?
ORM(Object Relational Mapping),對象關系映射,是一種為了解決關系型數據庫數據與簡單 Java 對象(POJO)建立映射關系的技術。
為什么說 Mybatis 是半自動ORM映射工具?它與全自動的區別在哪里?
具體流程:
① 加載配置文件:需要加載的配置文件包括全局配置文件(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信息封裝對象就使用它們訪問數據庫了,最后再返回操作結果,結束流程。
所謂三級緩存,其實就是org.springframework.beans.factory包下DefaultSingletonBeanRegistry類中的三個成員屬性:
Key:beanName
Value: Bean實例
private final Map<String, Object> singletonObjects=new ConcurrentHashMap<>(256);
Key:beanName
Value: Bean實例
和一級緩存一樣也是保存BeanName和創建bean實例之間的關系,與singletonObjects不同之處在于,當一個單例bean被放在里面后,那么bean還在創建過程中,就可以通過getBean方法獲取到了,其目的是用來循環檢測引用!
private final Map<String, Object> earlySingletonObjects=new ConcurrentHashMap<>(16);
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);
首先,Spring 解決循環依賴有兩個前提條件:
本質上解決循環依賴的問題就是依靠三級緩存,通過三級緩存提前拿到未初始化的對象。下面我們來看一個循環依賴的例子:
A 對象的創建過程:
1.創建對象A,實例化的時候把A對象工廠放入三級緩存
2.A 注入屬性時,發現依賴 B,轉而去實例化 B
3.同樣創建對象 B,注入屬性時發現依賴 A,一次從一級到三級緩存查詢 A,從三級緩存通過對象工廠拿到 A,把 A 放入二級緩存,同時刪除三級緩存中的 A,此時,B 已經實例化并且初始化完成,把 B 放入一級緩存。
4.接著繼續創建 A,順利從一級緩存拿到實例化且初始化完成的 B 對象,A 對象創建也完成,刪除二級緩存中的 A,同時把 A 放入一級緩存。
5.最后,一級緩存中保存著實例化、初始化都完成的A、B 對象。
從上面5步驟的分析可以看出,三級緩存解決循環依賴是通過把實例化和初始化的流程分開了,所以如果都是用構造器的話,就沒法分離這個操作(因為構造器注入實例化和初始是一起進行的)。因此構造器方式注入的話是無法解決循環依賴問題的。
解決循環依賴為什么必須要要三級緩存?二級不行嗎?
答案:不可以!
使用三級緩存而非二級緩存并不是因為只有三級緩存才能解決循環引用問題,其實二級緩存同樣也能很好解決循環引用問題。
使用三級而非二級緩存并非出于IOC的考慮,而是出于AOP的考慮,即若使用二級緩存,在AOP情形下,往二級緩存中放一個普通的Bean對象,BeanPostProcessor去生成代理對象之后,覆蓋掉二級緩存中的普通Bean對象,那么多線程環境下可能取到的對象就不一致了。
單例模式:Spring 中的 Bean 默認情況下都是單例的。無需多說。
工廠模式:工廠模式主要是通過 BeanFactory 和 ApplicationContext 來生產 Bean 對象。
代理模式:最常見的 AOP 的實現方式就是通過代理來實現,Spring主要是使用 JDK 動態代理和 CGLIB 代理。
…
單例模式
單例模式使?場景:
單例模式分類:
單例模式實現步驟:
工廠模式
??模式介紹:它提供了?種創建對象的最佳?式,在創建對象時 不會對客戶端暴露創建邏輯,并且是通過使??個共同的接?來指向新創建的對象。
??模式有 3 種不同的實現?式:
① 簡單??模式(靜態工廠):通過傳?相關的類型來返回相應的類,這 種?式?較單 ?,可擴展性相對較差。
② ???法模式:通過實現類實現相應的?法來決定相應的返回結果,這種?式的可擴展性?較強。
③ 抽象??模式:基于上述兩種模式的拓展,且?持細化產品。
應?場景:
解耦:分離職責,把復雜對象的創建和使?的過程分開。
復?代碼 降低維護成本:如果對象創建復雜且多處需?到,如果每處都進?編寫,則很多重復代碼,如果業務邏輯發?了改 變,需?四處修改;使???模式統?創建,則只要修改??類即可, 降低成本。
代理模式
代理模式最直觀的解釋就是,通過代理,將被代理對象 “增強”!(即,擴展被代理對象的功能)
代理模式分為靜態代理,和動態代理:動態代理的代理類是動態生成的 , 靜態代理的代理類是我們提前寫好的邏輯。
Java 中實現動態代理的方式有 2 種:
今日份分享已結束,請大家多多包涵和指點!
下流行的兩種企業開發MVC開源框架,是我們Java程序猿必備知識能力。MVC,即模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典范,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯聚集到一個部件里面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業務邏輯。框架之所以流行,在于其易復用和簡化開發,精髓在思想,掌握了核心思想,我們掌握其他類似框架也不會有問題,建議大家有精力的話讀一下框架源碼,尤其是Spring。
SSH和SSM定義
SSH 通常指的是 Struts2 做控制器(controller),spring 管理各層的組件,hibernate 負責持久化層。
SSM 則指的是 SpringMVC 做控制器(controller),Spring 管理各層的組件,MyBatis 負責持久化層。
共同點:1.Spring依賴注入DI來管理各層的組件。2.使用面向切面編程AOP管理事物、日志、權限等。
不同點:1.Struts2 和 SpringMVC 控制器(controller)控制視圖和模型的交互機制的不同,
Struts2是Action類級別,SpringMVC是方法級別,更容易實現RESTful風格。
SSH 和 SSM 的實現原理
1.Struts2 的實現原理
Struts2框架執行步驟(Struts2使用Filter嵌入):
1、客戶端初始化一個指向Servlet容器(例如Tomcat)的請求
2、這個請求經過一系列的過濾器(Filter)(這些過濾器中有一個叫做ActionContextCleanUp的可選過濾器,這個過濾器對于Struts2和其他框架的集成很有幫助
3、接著FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來決定這個請求是否需要調用某個Action
4、如果ActionMapper決定需要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy
5、ActionProxy通過Configuration Manager詢問框架的配置文件,找到需要調用的Action類
6、ActionProxy創建一個ActionInvocation的實例。
7、ActionInvocation實例使用命名模式來調用,在調用Action的過程前后,涉及到相關攔截器(Intercepter)的調用。
8、一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果通常是(但不總是,也可 能是另外的一個Action鏈)一個需要被表示的JSP或者FreeMarker的模版。
9、將處理結果返回給客戶端
2.SpringMVC 的實現原理
SpringMVC框架執行步驟(SpringMVC使用Servlet嵌入):
1、客戶端發出一個http請求給web服務器,web服務器對http請求進行解析,如果匹配DispatcherServlet的請求映射路徑(在web.xml中指定),web容器將請求轉交給DispatcherServlet.
2、DipatcherServlet接收到這個請求之后將根據請求的信息(包括URL、Http方法、請求報文頭和請求參數Cookie等)以及HandlerMapping的配置找到處理請求的處理器(Handler)。
3-4、DispatcherServlet根據HandlerMapping找到對應的Handler,將處理權交給Handler(Handler將具體的處理進行封裝),再由具體的HandlerAdapter對Handler進行具體的調用。
5、Handler對數據處理完成以后將返回一個ModelAndView()對象給DispatcherServlet。
6、Handler返回的ModelAndView()只是一個邏輯視圖并不是一個正式的視圖,DispatcherSevlet通過ViewResolver將邏輯視圖轉化為真正的視圖View。
7、Dispatcher通過model解析出ModelAndView()中的參數進行解析最終展現出完整的view并返回給客戶端。
Hibernate 和 MyBatis 兩種ORM框架對比
兩者的相同點
Hibernate與MyBatis都可以是通過SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session來開啟執行事務和SQL語句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。
Hibernate和MyBatis都支持JDBC和JTA事務處理。
兩者各自優勢
MyBatis可以進行更為細致的SQL優化,可以減少查詢字段。
MyBatis容易掌握,而Hibernate門檻較高。
Hibernate的DAO層開發比MyBatis簡單,Mybatis需要維護SQL和結果映射。
Hibernate對對象的維護和緩存要比MyBatis好,對增刪改查的對象的維護要方便。
Hibernate數據庫移植性很好,MyBatis的數據庫移植性不好,不同的數據庫需要寫不同SQL。
Hibernate有更好的二級緩存機制,可以使用第三方緩存。MyBatis本身提供的緩存機制不佳,更新操作不能指定刷新指定記錄,會清空整個表,但是也可以使用第三方緩存。
Hibernate 封裝性好,屏蔽了數據庫差異,自動生成SQL語句,應對數據庫變化能力較弱,SQL語句優化困難。
MyBatis僅實現了SQL語句和對象的映射,需要針對具體的數據庫寫SQL語句,應對數據庫變化能力較強,SQL語句優化較為方便。
總結
SSM和SSH不同主要在MVC實現方式,以及ORM持久化方面不同(Hiibernate與Mybatis)。SSM越來越輕量級配置,將注解開發發揮到極致,且ORM實現更加靈活,SQL優化更簡便;而SSH較注重配置開發,其中的Hiibernate對JDBC的完整封裝更面向對象,對增刪改查的數據維護更自動化,但SQL優化方面較弱,且入門門檻稍高。
附Spring家族:
熟悉當下流行的兩種企業開發MVC開源框架,是Java程序猿必備知識。MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫。M是指業務模型,V是指用戶界面,C則是控制器。一種軟件設計典范,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯聚集到一個部件里面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業務邏輯。小編在學校的時候學習過SSH,SSM則是去公司后用的。
SSH 通常指的是 Struts2 做前端控制器,Spring 管理各層的組件,Hibernate 負責持久化層。
SSM 則指的是 SpringMVC 做前端控制器,Spring 管理各層的組件,MyBatis 負責持久化層。
1.Struts2 的原理
Struts2框架執行過程:
1、客戶端初始化一個指向Servlet容器(例如Tomcat)的請求
2、這個請求經過一系列的過濾器(Filter)(這些過濾器中有一個叫做ActionContextCleanUp的可選過濾器,這個過濾器對于Struts2和其他框架的集成很有幫助,例如:SiteMesh Plugin
3、接著FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來決定這個請求是否需要調用某個Action,FilterDispatcher是控制器的核心,就是mvc中c控制層的核心
4、如果ActionMapper決定需要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy
5、ActionProxy通過Configuration Manager詢問框架的配置文件,找到需要調用的Action類
6、ActionProxy創建一個ActionInvocation的實例
7、ActionInvocation實例使用命名模式來調用,在調用Action的過程前后,涉及到相關攔截器(Intercepter)的調用
8、一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果通常是(但不總是,也可 能是另外的一個Action鏈)一個需要被表示的JSP或者FreeMarker的模版
9、將處理結果返回給客戶端
2.SpringMVC 的原理
SpringMVC框架執行過程:
1、客戶端發出一個http請求給web服務器,web服務器對http請求進行解析,如果匹配DispatcherServlet的請求映射路徑(在web.xml中指定),web容器將請求轉交給DispatcherServlet
2、DipatcherServlet接收到這個請求之后將根據請求的信息(包括URL、Http方法、請求報文頭和請求參數Cookie等)以及HandlerMapping的配置找到處理請求的處理器(Handler)
3、DispatcherServlet根據HandlerMapping找到對應的Handler,并返回
4、將處理權交給Handler(Handler將具體的處理進行封裝),再由具體的處理器適配器(HandlerAdapter)對Handler進行具體的調用
5、處理器適配器執行Handler
6、Handler對數據處理完成以后將返回一個ModelAndView對象給處理器適配器
7、處理器適配器向前端控制器返回ModelAndView
ModelAndView是springmvc框架的一個底層對象,包括Model和View
8、Handler返回的ModelAndView只是一個邏輯視圖并不是一個正式的視圖,前端控制器請求視圖解析器(ViewResolver)去進行視圖解析,根據邏輯視圖名解析成真正的視圖(jsp)
9、視圖解析器向前端控制器返回View
10、前端控制器進行視圖渲染,視圖渲染將模型數據(在ModelAndView對象中)填充到request域
11、前端控制器向用戶響應結果
3.Hibernate 的原理
Hibernate框架執行過程:
1.通過Configuration().configure();讀取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的讀取并解析映射信息
3.通過config.buildSessionFactory();//創建SessionFactory
4.sessionFactory.openSession();//打開Sesssion
5.session.beginTransaction();//創建事務Transation
6.persistent operate持久化操作
7.session.getTransaction().commit();//提交事務
8.關閉Session
9.關閉SesstionFactory
4、MyBatis原理
MyBatis框架執行過程:
1、配置MyBatis的配置文件,SqlMapConfig.xml(名稱不固定)
2、通過配置文件,加載MyBatis運行環境,創建SqlSessionFactory會話工廠SqlSessionFactory 在實際使用時按單例方式
3、通過SqlSessionFactory創建SqlSession,SqlSession 是一個面向用戶接口(提供操作數據庫方法),實現對象是線程不安全的,建議sqlSession應用場合在方法體內
4、調用 sqlSession 的方法去操作數據。如果需要提交事務,需要執行 SqlSession 的 commit() 方法
5、釋放資源,關閉SqlSession
Struts2和SpringMVC兩種框架對比
1.springmvc和struts2都是負責取轉發的,但是兩者針對request的請求上面區別很大。springmvc是針對于方法級別的請求的,也就是一個方法對應于一個請求,屬于方法攔截,請求的數據方法不共享;而struts2則是針對一個Action類來進行請求的,即一個Action類對應于一個請求,所以類攔截,請求的數據類共享
2.springmvc入口是一個servlet前端控制器(DispatcherServlet),struts2入口是一filter過濾器
3.springmvc的配置文件相對struts2來說較為少,容易上手,可以加快軟件開發的速度
Hibernate 和 MyBatis 兩種框架對比
相同之處
1.Hibernate與MyBatis都可以是通過SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session來開啟執行事務和SQL語句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的
2.Hibernate和MyBatis都支持JDBC和JTA事務處理
不同之處
1.Hibernate是一種O/R關系型,即完成數據庫表和持久化類之間的映射,而MyBitas是針對的SQL-Maping,個人理解是一種Hibernate把數據庫給封裝好以后,可以調用相應的數據庫操作語句HQL,而MyBitas則是用的原始的數據庫操作語句
2.針對高級查詢,Mybatis需要手動編寫SQL語句,以及ResultMap。而Hibernate有良好的映射機制,開發者無需關心SQL的生成與結果映射,可以更專注于業務流程
3.Hibernate優化起來相對MyBitas較難,而且Hibernate掌握起來相對MyBitas較難,但是Hibernate數據庫移植性很好,MyBatis的數據庫移植性不好,不同的數據庫需要寫不同SQL
Spring家族:
SSM和SSH相同之處在于都是用Spring依賴注入DI來管理各層的組件,并且都是使用面向切面編程AOP來管理事物、日志、權限等。不同之處在于MVC實現方式,以及ORM持久化方面不同(Hiibernate與Mybatis)。SSM越來越輕量級配置,將注解開發發揮到極致,且ORM實現更加靈活,SQL優化更簡便;而SSH較注重配置開發,其中的Hiibernate對JDBC的完整封裝更面向對象,對增刪改查的數據維護更自動化,但SQL優化方面較弱,且入門門檻稍高。
如果覺得不錯有幫助的,可以轉發點贊關注一下。謝謝!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。