天天看點

Jsp+Servlet+JavaBean到EJB,再到Spring,最後到SpringBoot 一、知史可以明鑒二、Web發展簡史三、Web發展初級階段六、總結

 一、知史可以明鑒

        我們學習技術的時代趕上了最好的時代,跳過了很多前人經常踩的坑,前人在踩坑的過程中總結了很多經驗和教訓,而新時代的我們隻是繼承了前人的經驗和教訓,而忽略了這些采坑的過程,以至于我們面對很多新技術都不知道他是什麼?他為什麼存在?他為什麼可以解決這個問題?更不知道如何掌握其原理!雲裡霧裡一頭霧水!

  交流群的很多小夥伴,常常私聊我讓我推薦一下學習SSM架構的視訊和資料,我首先會打開他的資料卡看一下他的年齡,如果超過了他這個年齡應有的水準,我就會問他JSP+Servlet學了嗎?很多小夥伴的回答是簡單的學了一下,然後,我會給他一個關于JSP+Servlet的實戰項目,順便給他們找一些SSM的項目,并且建議他們首先看這個JSP+Servlet的實戰項目。

  更有甚者,學了基礎之後就開始學習Spring Boot的,當問他們Spring Boot是什麼的時候,大緻也可以回答出來“約定大于配置”,“用起來很簡單”,但是在細究其原理,也是吱吱嗚嗚,一知半解!如果我們沒有經曆過Spring最開始繁瑣的配置、然後一步步精簡,根本體會不到為什麼會有Spring Boot這個東西!

  不先學習常見的設計模式直接看Spring、MyBatis等源碼,簡直就是一個找虐的過程!不掌握Servlet原理、基本的Tomcat容器技術上來就看Spring MVC源碼同樣也是一個打擊自信心的好地方!

  學習是一個循序漸進的過程,不能急于求成,但也不能過分鑽牛角尖!不能再一個技術上停滞不前,也不能如”蜻蜓點水”一般了了掠過!同樣,如果你還沒有掌握好Servlet和簡單的設計模式我建議你先去查閱相關的資料進行系統的學習。

  我也相信很多圖書或視訊等資料都忽略了講述為什麼會有Spring的過程,要麼是簡單概括并且痛斥EJB的各種弊端,要麼就是隻字不提,這是一種對讀者很不負責任的表現,知史可以明鑒!是以,在進一步學習Spring核心原理之前,我們有必要介紹一下整個Web發展的簡單曆史,一步步引出為什麼會有Spring!

二、Web發展簡史

     老一輩的軟體開發人員一般經曆了從Model1到Model2,然後到後來的三層模型,最後到現在的Spring Boot。如果從Model1到Model2說起到我們現在使用的Spring Boot為整個時間軸的話,大緻可以分為4個階段:

  (1)初級階段:使用Model1/Model2/三層模模型進行開發;

  (2)中級階段:使用EJB進行分布式應用開發,忍受重量級架構帶來的種種麻煩;

  (3)進階階段:使用Spring春天帶給我們的美好,但是還要忍受很多繁瑣的配置;

  (4)骨灰級階段:使用Spring Boot,暢享“預定大于配置”帶給我們的種種樂趣!

三、Web發展初級階段

1、Model1開發模式:

  Model1的開發模式是:JSP+JavaBean的模式,它的核心是Jsp頁面,在這個頁面中,Jsp頁面負責整合頁面和JavaBean(業務邏輯),而且渲染頁面,它的基本流程如下:

Jsp+Servlet+JavaBean到EJB,再到Spring,最後到SpringBoot 一、知史可以明鑒二、Web發展簡史三、Web發展初級階段六、總結

 相信很多小夥伴在剛學習Web的時候,肯定使用到了Model1開發模式,也就是我們的業務代碼、持久化代碼直接寫在Jsp頁面裡邊,使用Jsp直接處理Web浏覽器的請求,并使用JavaBean處理業務邏輯。

  利用我們現在熟悉的MVC模型的思想去看,雖然編寫代碼十分容易,但Jsp混淆了MVC模型中的視圖層和控制層,高度耦合的結果是Jsp代碼十分複雜,後期維護困難!

2、Model2開發模式:

        Model1雖然在一定程度上解耦了,但JSP依舊即要負責頁面控制,又要負責邏輯處理,職責不單一!此時Model2應運而生,使得各個部分各司其職,Model2是基于MVC模式的。

  Model2的開發模式是:Jsp+Servlet+JavaBean的模式,它和Model1不同的是,增加了Servlet,将調用頁面資料,調用業務邏輯等工作放到了Servlet中處理,進而減輕了Jsp的工作負擔!它的基本流程如下:

Jsp+Servlet+JavaBean到EJB,再到Spring,最後到SpringBoot 一、知史可以明鑒二、Web發展簡史三、Web發展初級階段六、總結

Model2開發模式将Servlet的概念引入架構體系中,使用它來配置設定視圖層Jsp的顯示頁面,同時調用模型層的JavaBean來控制業務邏輯。

3、Model1和Model2的差別:

        Model1:簡單,适合小型項目的開發,但是Jsp的職責過于繁重,職責分工不明确。在後期的維護工作中,必将為此付出代價!

  Model2:相對于Model1來說,職責分工更為明确,在Model1的基礎上,抽取了Servlet層,展現了一個分層的思想,适合大型的項目開發!(當時的評判标準是适合大型項目開發的,現在看起來已經過時了!)

  Model2看起來已經盡善盡美了,盡管如此,他還不能稱之為一個比較完善的MVC設計模式!

 4、Model1和Model2與三層的對比:

        在Model2中,我們将Servlet抽取出單獨的一層,和Jsp協作完成使用者資料互動的工作,也就是表示層。那麼作為三層結構來說,又做了什麼樣的改進呢?三層則是在此基礎上,将JavaBean再一次進行分割:業務邏輯、資料持久化,三層如下:

  (1)表示層,JSP/Servlet;

  (2)業務邏輯層:業務規則;

  (3)持久化層:主要包裝持久化的邏輯 ;

  

Jsp+Servlet+JavaBean到EJB,再到Spring,最後到SpringBoot 一、知史可以明鑒二、Web發展簡史三、Web發展初級階段六、總結

  各個的耦合性如下圖:

  

Jsp+Servlet+JavaBean到EJB,再到Spring,最後到SpringBoot 一、知史可以明鑒二、Web發展簡史三、Web發展初級階段六、總結

  Model1、Model2、三層是在解耦的基礎上一步步進化而來,通過解耦我們可以進行進一步的抽象,以應對現實需求的變動。

四、Web發展中級階段、進階階段和骨灰級階段

  這一小節似乎有點應付,對于中級階段,因為我沒有用過EJB,在這裡不敢妄加評論,以免誤導大家。但是相信每一位接觸過Spring的小夥伴,都應該知道Rod Johnson在2002年編寫的《Expert One-to-One J2EE Design and Development》一書,Rod 在本書中對J2EE正統架構臃腫、低效、脫離現實的種種學院派做法提出了質疑,并以此書為指導思想,編寫了interface21架構,也就是後來的Spring。

  對于進階階段和骨灰級階段是我們後期一系列文章的重點,本篇隻作為一個階段劃分,不做過多的解釋,是以讓我們重新回到Web發展的初級階段。

  對EJB有興趣的可以參考文章:http://www.uml.org.cn/j2ee/2009112011.asp

五、Web發展初級階段存在的問題

        經曆過初級階段的小夥伴肯定看得懂下邊的一個項目結構,一個簡單的MVC三層結構,使用JSP+Servlet+MySQL+JDBC技術,面向接口程式設計:

  

Jsp+Servlet+JavaBean到EJB,再到Spring,最後到SpringBoot 一、知史可以明鑒二、Web發展簡史三、Web發展初級階段六、總結

1、面向接口程式設計的執行個體化對象

  以使用者管理子產品為例,有一個UserDao接口,有一個接口的實作類UserDaoImpl,如下:

  

Jsp+Servlet+JavaBean到EJB,再到Spring,最後到SpringBoot 一、知史可以明鑒二、Web發展簡史三、Web發展初級階段六、總結

  由于是面向接口程式設計,是以我們在每次使用UserDao的時候,都要進行執行個體化一次,執行個體化代碼如下:

  UserDao userDao = new UserDaoImpl();

  我們在每次使用UserDao的時候都需要進行執行個體化,當然不僅僅有UserDao需要進行執行個體化,還有很多需要進行執行個體化的,舉例如下:

Jsp+Servlet+JavaBean到EJB,再到Spring,最後到SpringBoot 一、知史可以明鑒二、Web發展簡史三、Web發展初級階段六、總結

  

  可以看出,每一個方法中都需要進行執行個體化我們需要用到的接口的實作類,這就會存在大量的執行個體化對象,并且他們的生命周期可能就是從方法的調用開始到方法的調用結束為止,加大了GC回收的壓力!

2、使用單例模式的一次改進

  了解設計模式的可能會想到使用單例模式的方式來解決這個問題,以此來避免大量重複的建立對象,但是我們還要考慮到衆多的這種對象的建立都需要改成單例模式的話,是一個耗時耗力的操作。

  對于這個系統來說,如果都把這種面向接口的對象實作類轉換為單例模式的方式的話,大概也要寫十幾個或者上百個這種單例模式代碼,而對于一個單例模式的寫法來說,往往是模闆式的代碼,以靜态内部類的方式實作代理模式如下:

  

Jsp+Servlet+JavaBean到EJB,再到Spring,最後到SpringBoot 一、知史可以明鑒二、Web發展簡史三、Web發展初級階段六、總結

  可以看出,這種方式有兩個問題:

  (1)業務代碼與單例模式的模闆代碼放在一個類裡,耦合性較高;

  (2)大量重複的單例模式的模闆代碼;

  從上述可以看出,使用的單例模式雖然從性能上有所提高,但是卻加重了我們的開發成本。是以隻會小規模的使用,例如我們操作JDBC的Utils對象等。

3、我們開發中遇到的痛點

  從上述代碼的演進過程我們可以看得出來,我們即需要一個單例的對象來避免系統中大量重複對象的建立和銷毀,又不想因為使用單例模式造成大量重複無用的模闆代碼和代碼的耦合!

  (突然想到一個段子,想和大家分享一下:産品經理在給甲方彙報方案的時候說了兩種方案:一種是實用的,一種是美觀的,問甲方希望選擇哪一種?甲方說:有沒有即實用又美觀的!)

4、我們還能怎麼做

  作為學院派的書生來說,我們可能會聯想到“資料庫連接配接池”,我們在擷取資料庫連接配接的時候會從這個池子中拿到一個連接配接的,假設這個資料庫連接配接池很特殊,有且隻能有N個資料庫連接配接,并且每一個連接配接對象都不同(假設),那麼這個不就相當于每一個連接配接都是單例的了嗎?既可以避免大量對象的建立,也可以實作不會出現大量重複性的模闆代碼。

  是以,這裡應該有一個大膽的想法,我們是否可以建立一個池子,将我們的接口實作類對象放入到這個池子中,我們在使用的時候直接從這個池子裡邊取就行了!

  5、這個池子

  如果我們要建立這個池子,首先要确定需要把哪些對象放進這個池子,通過怎樣的方式放進去,放進去之後如何進行管理,如何進行擷取,池子中的每一個對象的生命周期是怎麼樣的等等這些東西都是我們需要考慮到的!

  6、恭喜你

  如果你已經了解了上述Web演進的過程,以及我們想要建立的這個池子,那麼恭喜你!你已經打開了Spring核心原理的大門了!

  上述我們想要建立的池子其實就是Spring容器的雛形,将接口實作類的對象放進池子進行管理的過程其實也是Spring IOC依賴注入、控制反轉的雛形!

  Spring的依賴注入/控制反轉就是從我們的配置檔案或注解中的得到我們需要進行注入到Spring容器的實作類的資訊,Spring IOC通過這些配置資訊建立一個個單例的對象并放入Spring容器中,Spring容器可以看做是一個集合儲存着我們的這些對象。

  7、小總結

  上文中主要從一個切入點探讨了一下為什麼有Spring,以及介紹了一下Spring IOC和Spring容器的基本雛形概念,當然還可以從其他方面進行切入。這裡沒有進一步探讨AOP的概念,對于新入門的小夥伴來說,這個确實有必要讨論一下,也決定在後續文章中由淺入深的探讨一下,而對于老手來說,其實我上邊寫的基本上是浪費大家時間的!

六、總結

  從曆史的角度來說,不同時期的大革命在爆發之前,都會有一個蓄謀已久的“導火線”!Spring的出現,同樣順應了曆史發展潮流,正式由于那個時期J2EE開發标準的種種弊端造就了Spring的出現!即使不是Spring,同樣也會有其他類似的産品出現,隻不過曆史選擇了Spring,Spring順應了曆史!沒有切膚之痛,是不會體會到Spring帶給我們的樂趣與快感!

  同樣的,每個時代都會有每一個時代的問題,Spring也是!正如十年前我們的計算機可能帶不動一款遊戲,今天我們的計算機也有可能帶不動一款如今的遊戲,同樣十年後的計算機也會有一款他帶不動的遊戲出現!以一種發展的眼光去看Spring,就可以很好的了解Spring Boot是以一種什麼樣的角色出現在我們的面前了!

  時代選擇了Spring,同樣Spring也被這個時代所選擇着!你我隻有不停的進步,不停地學習才能跟上這個時代!

原文位址:Spring的誕生史 - 環信