1. 程式人生 > 實用技巧 >SSM三大框架的執行流程、原理、核心技術詳解!

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方法”,這裡也體現了注入了概念
  • 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…)
  • 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、每張表重要的欄位設定
      • 非空欄位、外來鍵欄位
  • 3、資料庫級別表與表之間的關係

    • 外來鍵關係
  • 4、表與表之間的業務關係

    • 在分析表與表之間的業務關係時一定要建立在 某 個 業 務 意 義 基 礎 上 去 分 析 。 \color{red}{在某個業務意義基礎上去分析。}