SSM三大框架的執行流程、原理、核心技術詳解!
一、Spring部分
1、Spring的執行流程
- 第一步:載入配置檔案
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
,ApplicationContext介面,它由BeanFactory介面派生而來,因而提供了BeanFactory所有的功能。配置檔案中的bean的資訊是被載入在HashMap中的,一個bean通常包括,id,class,property等,bean的id對應HashMap中的key,value呢就是bean
具體如何載入?原始碼如下:
if (beanProperty.element("map") != null){
Map<String, Object> propertiesMap = new HashMap<String, Object>();
Element propertiesListMap = (Element)beanProperty.elements().get(0);
Iterator<?> propertiesIterator = propertiesListMap .elements().iterator();
while (propertiesIterator.hasNext()) {
Element vet = (Element) propertiesIterator.next();
if(vet.getName().equals("entry")) {
String key = vet.attributeValue("key");
Iterator<?> valuesIterator = vet.elements() .iterator();
while (valuesIterator.hasNext()) {
Element value = (Element) valuesIterator.next();
if (value.getName().equals("value")){
propertiesMap.put(key, value.getText());
}
if (value.getName().equals("ref")) {
propertiesMap.put(key, new String[]{
value.attributeValue("bean")
});
}
}
}
}
bean.getProperties().put(name, propertiesMap);
//看完反正我是默默放棄了。。。
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 第二步:呼叫getBean方法,getBean是用來獲取applicationContext.xml檔案裡bean的,()寫的是bean的id。一般情況都會強轉成我們對應的業務層(介面)。例如
SpringService springService =(SpringService)ac.getBean("Service");
- 第三步:這樣我們就可以呼叫業務層(介面實現)的方法。
具體如下:
Java反射博大精深,我也不很懂,具體請檢視Java基礎之—反射
那麼bean中的東西到底是怎麼注入進去的?簡單來講,就是在例項化一個bean時,實際上就例項化了類,它通過反射呼叫類中set方法將事先儲存在HashMap中的類屬性注入到類中。這樣就回到了我們Java最原始的地方,物件.方法,物件.屬性
2、Spring的原理
-
什麼是spring?
-
spring是一個容器框架,它可以接管web層,業務層,dao層,持久層的各個元件,並且可以配置各種bean, 並可以維護bean與bean的關係,當我們需要使用某個bean的時候,我們可以直接getBean(id),使用即可
-
Spring目的:就是讓物件與物件(模組與模組)之間的關係沒有通過程式碼來關聯,都是通過配置類說明管理的(Spring根據這些配置 內部通過反射去動態的組裝物件) ,Spring是一個容器,凡是在容器裡的物件才會有Spring所提供的這些服務和功能。
-
層次框架圖:
說明:- web層:struts充當web層,接管jsp,action,表單,主要體現出mvc的資料輸入,資料的處理,資料的顯示分離
- model層:model層在概念上可以理解為包含了業務層,dao層,持久層,需要注意的是,一個專案中,不一定每一個層次都有
- 持久層:體現oop,主要解決關係模型和物件模型之間的阻抗
3、Spring的核心技術
-
IOC
- ioc(inverse of control)控制反轉:所謂反轉就是把建立物件(bean)和維護物件(bean)之間的關係的權利從程式轉移到spring的容器(spring-config.xml)
說明:<bean></bean>
這對標籤元素的作用:當我們載入spring框架時,spring就會自動建立一個bean物件,並放入記憶體相當於我們常規的new一個物件,而<property></property>
中的value則是實現了“物件.set方法”,這裡也體現了注入了概念
- ioc(inverse of control)控制反轉:所謂反轉就是把建立物件(bean)和維護物件(bean)之間的關係的權利從程式轉移到spring的容器(spring-config.xml)
-
DI
- di(dependency injection)依賴注入:實際上di和ioc是同一個概念,spring的設計者,認為di更準確的表示spring的核心
- spring提倡介面程式設計,在配合di技術就可以達到層與層解耦的目的,為什麼呢?因為層與層之間的關聯,由框架幫我們做了,這樣程式碼之間的耦合度降低,程式碼的複用性提高
- 介面程式設計的好處請訪問Java中介面程式設計的好處以及實現方式的選擇?
-
AOP
- aspect oriented programming(面向切面程式設計)
- 核心:在不增加程式碼的基礎上,還增加新功能
- 理解:面向切面:其實是,把一些公共的“東西”拿出來,比如說,事務,安全,日誌,這些方面,如果你用的到,你就引入。也就是說:當你需要在執行一個操作(方法)之前想做一些事情(比如,開啟事務,記錄日誌等等),那你就用before,如果想在操作之後做點事情(比如,關閉一些連線等等),那你就用after。其他類似
2019-09-03 補充 :
內容取自《spring原始碼解析》
spring整體架構圖:
1、core container(核心容器)
核心容器包含了core,beans,context和expression language四個模組
core和beans模組是框架的基礎部分,提供IOC和依賴注入特性。這裡的基礎概念是BeanFactory,它提供對Factory模式的經典實現來消除對程式性單例模式的需要,並真正地允許你從程式邏輯中分離出依賴關係和配置。
-
core模組主要包含了spring框架基本的黑犀牛工具類,spring的其他組建都要用到這個包裡的類,core模組是其他元件的基本核心。當然你也可以在自己應用系統中使用這些工具類。
-
beans模組是所有應用都要用到的,它包含訪問配置檔案,建立和管理bean以及進行ioc,di操作相關的所有類
-
context模組構建與core和beans模組基礎之上,提供了一種類似於JNDI註冊器的框架式的物件訪問方法。context模組繼承了beans的特性,為spring核心提供了大量擴充套件,添加了對國際化(例如資源繫結)、事件傳播、資源載入和對context的透明建立的支援。context模組同事也支援j2ee的一些特性,例如EJB,JMX和基礎的遠端處理,applicationContext介面是context模組的關鍵。
-
ExpressionLanguage模組提供了強大的表示式語言,用於在執行時查詢和操縱物件。他是jsp2.1規範中定義的unifed expression language的擴充套件。該語言支援設定/獲取屬性的值,屬性的分配,方法的呼叫 ,訪問陣列上下文,容器和索引器,邏輯和算數運算子,命名變數以及從spring的ioc容器中根據名稱檢索物件。它也支援list投影,選擇和一般的list聚合
2、Date Access/Integration
Date Access/Integration層包含JDBC,ORM,OXM,JMS和Transaction模組
-
jdbc模組提供了一個jdbc抽象層,他可以消除冗長的jdbc編碼和解析資料廠商特有的錯誤程式碼。這個模組包含了spring對jdbc資料訪問進行封裝的所有類。
-
orm模組為流行的物件-關係對映API,如JPA,JDO,Hibernate,iBatis等,提供了一個互動層。利用ORM封裝包,可以混合使用所有spring提供的特性進行O/R對映,如前邊提到的簡單宣告性事務管理。spring框架插入了若干個ORM框架 ,從而提供了ORM的物件關係工具,其中包括JDO,hibernate和iBatisSQl Map。所有這些都遵從spring的通用事務和DAO異常層次結構。
-
OXM模組提供了一個對Object/XML對映實現的抽象層,Object/XML對映實現包括JAXB,Castor,XMLBeans,JiBX和XStream。
-
JMS(java massage service)模組主要包含了一些製造和消費訊息的特性
-
Transaction模組支援程式設計和宣告性的事務管理,這些事務類必須實現特地的介面。並且對多有的POJO都適用
3、web
web上下文模組建立在應用程式上下文模組之上,為基於web的應用程式提供了上下文。所以,spring框架支援與Jakarta struts的整合。web模組還簡化了處理大部分請求以及將請求引數繫結到域物件的工作。web層包含了web,web-servlet,web-Struts 和web-porlet
- web模組,提供了基礎的面向web的整合特性。例如:多檔案上傳,使用servlet listeners初始化 Ioc容器已經一個面向web的應用上下文。它還包含spring遠端支援中的web的相關部分。
- web-servlet模組web.servlet.jar:該模組包含spring的model-view-controller(mvc)實現。spring的mbc框架使得模型範圍內的程式碼和webforms之間能夠清楚地分離出來。並與spring框架的其他特性整合在一起。
- web-Struts模組,該模組提供了對struts的支援,使得類在spring應用中能夠與一個典型的struts web層整合在一起。注意,該支援在spring3.0中已被棄用。
- web-portlet模組,提供了用於portlet環境和web-servlet模組的MVC的實現。
4、AOP
aop模組提供了一個符合aop聯盟標準的面向切面程式設計的實現,它讓你可以定義例如方法攔截器和切點,從而將邏輯程式碼分開,降低它們之間的耦合性。利用source-level的元資料功能,還可以將各種行為資訊合併到你的程式碼中,這有點像.Net技術中的attribute概念
通過配置管理特性,springAop模組直接將面向介面的程式設計功能整合到了spring框架中,所以可以很容易地使用spring框架管理的任何物件支援aop,springAop模組為基於spring的應用程式中的物件提供了事務管理服務。通過使用springAop,不用歷來EJB元件,就可以將宣告性事務管理整合到應用程式中。
- Aspects模組提供了AspectJ的整合支援。
- Instrumentation模組提供了class Instrumentation支援和classloader實現,使用可以再特定的應用伺服器上使用。
5、Test
test模組支援使用JUnit和TestNG對spring元件進行測試。
二、Spring MVC部分
1、Spring MVC的執行流程
- springMVC框架
框架執行流程(面試必問)- 1、使用者傳送請求至前端控制器DispatcherServlet
- 2、DispatcherServlet收到請求呼叫HandlerMapping處理器對映器。
- 3、處理器對映器根據請求url找到具體的處理器,生成處理器物件及處理器攔截器(如果有則生成)一併返回給DispatcherServlet。
- 4、DispatcherServlet通過HandlerAdapter處理器介面卡呼叫處理器
- 5、執行處理器(Controller,也叫後端控制器)。
- 6、Controller執行完成返回ModelAndView
- 7、HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet
- 8、DispatcherServlet將ModelAndView傳給ViewResolver檢視解析器
- 9、ViewResolver解析後返回具體View
- 10、DispatcherServlet對View進行渲染檢視(即將模型資料填充至檢視中)。
- 11、DispatcherServlet響應使用者
2、Spring MVC的原理
-
1、什麼是SpringMVC?
-
springmvc是spring框架的一個模組,springmvc和spring無需通過中間整合層進行整合。
-
springmvc是一個基於mvc的web框架。
-
mvc
- mvc在b/s系統 下的應用:
- 前端控制器DispatcherServlet(不需要程式設計師開發)
- 作用接收請求,響應結果,相當於轉發器,中央處理器。有了DispatcherServlet減少了其它元件之間的耦合度。
- 處理器對映器HandlerMapping(不需要程式設計師開發)
- 作用:根據請求的url查詢Handler
- 處理器介面卡HandlerAdapter
- 作用:按照特定規則(HandlerAdapter要求的規則)去執行Handler
- 處理器Handler(需要程式設計師開發)
- 注意:編寫Handler時按照HandlerAdapter的要求去做,這樣介面卡才可以去正確執行Handler
- 檢視解析器View resolver(不需要程式設計師開發)
- 作用:進行檢視解析,根據邏輯檢視名解析成真正的檢視(view)
- 檢視View(需要程式設計師開發)
- View是一個介面,實現類支援不同的View型別(jsp、freemarker、pdf…)
- mvc在b/s系統 下的應用:
-
struts2與springMVC的區別?
1、Struts2是類級別的攔截,一個類對應一個request 上下文, SpringMVC是方法級別的攔截,一個方法對應一個request上下文,而方法同時又跟一個url對應,,所以說從架構本身上SpringMVC就容易實現restful url,而struts2的架構實現起來要費勁,因為Struts2中Action的一個方法可以對應一個url ,而其類屬性卻被所有方法共享,這也就無法用註解或其他方式標識其所屬方法了。
2、由上邊原因, SpringMVC的方法之間基本上獨立的,獨享request response資料,請求資料通過引數獲取,處理結果通過ModelMap交回給框架,方法之間不共享變數,而Struts2搞的就比較亂,雖然方法之間也是獨立的,但其所有Action變數是共享的,這不會影響程式執行,卻給我們編碼讀程式時帶來麻煩,每次來了請求就建立一個Action ,一個Action物件對應一個request 上下文。
3、由於Struts2需要針對每個request進行封裝,把request , session等servlet生命週期的變數封裝成一個一 個Map,供給每個Action使用,並保證執行緒安全,所以在原則上,是比較耗費記憶體的。
4、攔截器實現機制上, Struts2有以自己的interceptor機制,SpringMVC用的是獨立的AOP方式,這樣導致Struts2的配置檔案量還是比SpringMVC大。
5、SpringMVC的入口是servlet ,而Struts2是filter (這裡要指出, filter和servlet是不同的。以前認為filter是servlet的一種特殊),這就導致 了二者的機制不同,這裡就牽涉到servlet和filter的區別了。
6、SpringMVC集成了Ajax ,使用非常方便,只需一個註解@ResponseBody就可以實現,然後直接返回響應文字即可,而Struts2攔截器集成了Ajax ,在Action中處理時一般必須安裝外掛或者自己寫程式碼整合進去,使用起來也相對不方便。
7、SpringMVC驗證支援JSR303 ,處理起來相對更加靈活方便,而Struts2驗證比較繁瑣,感覺太煩亂。
8、Spring MVC和Spring是無縫的。從這個專案的管理和安全上也比Struts2高(當然Struts2也可以通過不同的目錄結構和相關配置做到SpringMVC-樣的效果,但是需要xml配置的地方不少)。
9、設計思想上,Struts2更加符合0OP的程式設計思想,SpringMVC就比較謹慎,在servlet上擴充套件。
10、SpringMVC開發效率和效能高於Struts2。
11、SpringMVC可以認為已經100%零配置。
3、Spring MVC的核心技術
- 註解開發(@Controller,@RequestMapping,@ResponseBody。。。。)
- 還有Spring的諸多註解,這兩者是不需要整合的~
- 傳參,接參(request)
- 基本配置
- 檔案上傳與下載
- Spring MVC中檔案上傳需要新增Apache Commons FileUpload相關的jar包,
- 基於該jar, Spring中提供了MultipartResolver實現類: CommonsMultipartResolver.
- 攔截器
- 其實最核心的還是SpringMVC的執行流程,各個點的作用得搞清楚。
三、Mybatis部分
1、Mybatis的執行流程
- Mybatis執行流程圖:
第一步:配置檔案mybatis.xml,大體如下,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引入外部檔案
resource:引入專案中配置檔案
url:引入網路中或者路徑檔案
-->
<properties resource="jdbc.properties"/>
<settings>
<!--<setting name="mapUnderscoreToCamelCase" value="true" />-->
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false" />
<setting name="cacheEnabled" value="true"/>
</settings>
<typeAliases>
<package name="com.nuc.entity"></package>
</typeAliases>
<!-- - - - - - - 資料庫環境配置- - - - - - - - - -->
<environments default="environments">
<environment id="environments">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.jdbcUrl}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- - - - - - - -對映檔案路徑- - - - - - -->
<mappers>
<!--自動掃描包下的對映檔案,要求:同名,同目錄-->
<package name="com.nuc.mapper" />
</mappers>
</configuration>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
第二步:載入我們的xml檔案
第三步:建立SqlSessionFactoryBuilder
第四步:建立SqlSessionFactory
第五步:呼叫openSession(),開啟sqlSession
第六步:getMapper()來獲取我們的mapper(介面),mapper對應的對映檔案,在載入mybatis.xml時就會載入
第七步:使用我們自己的mapper和它對應的xml來完成我們和資料庫互動。即增刪改查。
第八步:提交session,關閉session。
程式碼如下:
String resource = "mybatis-config.xml";
SqlSession sqlSession = null;
InputStream inputStream = Resources.getResourceAsStream(resource);//讀取mybatis配置檔案
//SqlSessionFactoryBuilder這個類的作用就是為了建立SqlSessionFactory的
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
/**
* factory.openSession(); //需手動提交事務
* factory.openSession(true); //系統自動提交事務
*/
sqlSession = factory.openSession();
CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
//增刪改查的操作
sqlSession.commit();//如果沒有提交,資料庫的資料不會改變
sqlSession.close();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
需要注意的是,sqlSession也自帶一些資料互動的操作
2、Mybatis的原理
-
什麼是Mybatis?
- mybatis專注sql本身,需要程式設計師自己編寫sql語句,sql修改、優化比較方便。mybatis是一個不完全 的ORM框架,雖然程式設計師自己寫sql,mybatis 也可以實現對映(輸入對映、輸出對映)。
- mybatis是一個持久層的框架,是apache下的頂級專案。
- mybatis託管到goolecode下,後來託管到github下:mybatis Github地址
- mybatis讓程式將主要精力放在sql上,通過mybatis提供的對映方式,自由靈活生成(半自動化,大部分需要程式設計師編寫sql)滿足需要sql語句。
- mybatis可以將向 preparedStatement中的輸入引數自動進行輸入對映,將查詢結果集靈活對映成java物件。(輸出對映)
-
mybatis底層實現
- mybatis底層還是採用原生jdbc來對資料庫進行操作的,只是通過 SqlSessionFactory,SqlSession Executor,StatementHandler,ParameterHandler,ResultHandler和TypeHandler等幾個處理器封裝了這些過程
-
對原生態jdbc程式(單獨使用jdbc開發)問題總結:
- 1、資料庫連線,使用時建立,不使用就關閉,對資料庫進行頻繁連線開啟和關閉,造成資料庫資源的浪費
解決:使用資料庫連線池管理資料庫連線
- 2、將sql 語句硬編碼到Java程式碼中,如果sql語句修改,需要對java程式碼重新編譯,不利於系統維護
解決:將sql語句設定在xml配置檔案中,即使sql變化,也無需重新編譯
- 3、向preparedStatement中設定引數,對佔位符位置和設定引數值,硬編碼到Java檔案中,不利於系統維護
解決:將sql語句及佔位符,引數全部配置在xml檔案中
- 4、從resutSet中遍歷結果集資料時,存在硬編碼,將獲取表的欄位進行硬編碼,不利於系統維護。
解決:將查詢的結果集,自動對映成java物件
-
mybatis工作原理
- mybatis通過配置檔案建立sqlsessionFactory,sqlsessionFactory根據配置檔案,配置檔案來源於兩個方面:一個是xml,一個是Java中的註解,獲取sqlSession。SQLSession包含了執行sql語句的所有方法,可以通過SQLSession直接執行對映的sql語句,完成對資料的增刪改查和事物的提交工作,用完之後關閉SQLSession。
3、Mybatis的核心技術
-
Mybatis輸入對映
- 通過parameterType指定輸入引數的型別,型別可以是簡單型別、hashmap、pojo的包裝型別
-
Mybatis輸出對映
-
一、resultType
-
作用:將查詢結果按照sql列名pojo屬性名一致性對映到pojo中。
-
使用resultType進行輸出對映,只有查詢出來的列名和pojo中的屬性名一致,該列才可以對映成功。
-
如果查詢出來的列名和pojo中的屬性名全部不一致,則不會建立pojo物件。
-
只要查詢出來的列名和pojo中的屬性有一個一致,就會建立pojo物件
-
如果查詢出來的列名和pojo的屬性名不一致,通過定義一個resultMap對列名和pojo屬性名之間作一個對映關係。
-
-
二、resultMap
- 使用association和collection完成一對一和一對多高階對映(對結果有特殊的對映要求)。
- association:
- 作用:將關聯查詢資訊對映到一個pojo物件中。
- 場合:為了方便查詢關聯資訊可以使用association將關聯訂單資訊對映為使用者物件的pojo屬性中,比如:查詢訂單及關聯使用者資訊。
- 使用resultType無法將查詢結果對映到pojo物件的pojo屬性中,根據對結果集查詢遍歷的需要選擇使用resultType還是resultMap。
- collection:
- 作用:將關聯查詢資訊對映到一個list集合中。
- 場合:為了方便查詢遍歷關聯資訊可以使用collection將關聯資訊對映到list集合中,比如:查詢使用者許可權範圍模組及模組下的選單,可使用collection將模組對映到模組list中,將選單列表對映到模組物件的選單list屬性中,這樣的作的目的也是方便對查詢結果集進行遍歷查詢。如果使用resultType無法將查詢結果對映到list集合中。
-
-
Mybatis的動態sql
-
什麼是動態sql?
- mybatis核心 對sql語句進行靈活操作,通過表示式進行判斷,對sql進行靈活拼接、組裝。
- 包括, where ,if,foreach,choose,when,otherwise,set,trim等標籤的使用
-
資料模型分析思路
- 1、每張表記錄的資料內容
- 分模組對每張表記錄的內容進行熟悉,相當 於你學習系統 需求(功能)的過程
- 2、每張表重要的欄位設定
- 非空欄位、外來鍵欄位
- 1、每張表記錄的資料內容
-
3、資料庫級別表與表之間的關係
- 外來鍵關係
-
4、表與表之間的業務關係
- 在分析表與表之間的業務關係時一定要建立在 某 個 業 務 意 義 基 礎 上 去 分 析 。 \color{red}{在某個業務意義基礎上去分析。}在某個業務意義基礎上去分析。