終於又靜下來繼續寫這個主題的續篇,前六篇主要講了一些J2se方面的經驗和感受, 眼下Java應用范圍已經被J2ee占據了相當大的一塊領域,有些人甚至聲稱Java被J2ee所取代了。不知道大家如何來理解所謂的J2ee (Java2 Enterprise Edition),也就是Java企業級應用?
筆者的觀點是,技術的發展是順應世界變化的趨勢的,從C/S過渡到B/S模式,從客戶端的角度考慮企業級應用或者說電子商務領域不在關心客戶端維護問題,這個任務已經交給了任何一台PC都會有的浏覽器去維護;從服務器端的角度考慮,以往C/S中的TCP/IP協議實現載體ServerSocket被Web Server Container所取代,例如大家都很熟悉的Tomcat、JBoss、WebLogic等等。總之一切的轉變都是為了使得Java技術能更好的為人類生產生活所服務。
有人會問,直接去學J2ee跳過J2se行否?筆者是肯定不贊成的,實際上確實有人走這條路,但筆者自身體會是正是由於J2se的基礎很牢固,才會導致在J2ee學習的道路上順風順水,知識點上不會有什麼迷惑的地方。舉個簡單的例子吧:
筆者曾經跟大學同學討論下面這兩種寫法的區別:
ArrayList list=new ArrayList(); //筆者不說反對,但至少不贊成
List list=new ArrayList(); //筆者支持
曾經筆者跟同學爭論了幾個小時,他非說第一種寫法更科學,第二種完全沒有必要。我無法完全說服他,但筆者認為良好的習慣和意識是任何時候都應該針對接口編程,以達到解耦合和可擴展性的目的。下面就以接口開始進入J2ee的世界吧:
1.J2ee與接口
每一個版本的J2ee都對應著一個確定版本的JDK,J2ee1.4對應Jdk1.4,現在比較新的是JDK5.0,自然也會有J2EE 5.0.其實筆者一直在用的是J2EE1.4,不過沒什麼關系,大家可以下任何一個版本的J2ee api來稍微浏覽一下。筆者想先聲明一個概念,J2ee也是源自Java,所以底層的操作依然調用到很多J2se的庫,所以才建議大家先牢牢掌握J2se 的主流技術。
J2ee api有一個特點,大家比較熟悉的幾個包java.jms、javax.servlet.http、javax.ejb等都以interface居多,實現類較少。其實大家真正在用的時候百分之六十以上都在反復的查著javax.servlet.http這個包下面幾個實現類的api函數,其他的包很少問津。筆者建議在學習一種技術之前,對整體的框架有一個了解是很有必要的,J2ee旨在通過interface的聲明來規范實現的行為,任何第三方的廠商想要提供自己品牌的實現前提也是遵循這些接口定義的規則。如果在從前J2se學習的道路上對接口的理解很好的話,這裡的體會將是非常深刻的,舉個簡單的例子:
public interface Mp3{
public void play();
public void record();
public void stop();}
如果我定義這個簡單的接口,發布出去,規定任何第三方的公司想推出自己的名字為Mp3的產品都必須實現這個接口,也就是至少提供接口中方法的具體實現。這個意義已經遠遠不止是面向對象的多態了,只有廠商遵循J2ee的接口定義,世界上的J2ee程序員才能針對統一的接口進行程序設計,最終不用改變代碼只是因為使用了不同廠商的實現類而有不同的特性罷了,本質上說,無論哪一種廠商實現都完成了職責范圍內的工作。這個就是筆者想一直強調的,針對接口編程的思想。
接口到底有什麼好處呢?我們這樣設想,現在有AppleMp3、SonyMp3、SamsungMp3都實現了這個Mp3的接口,於是都有了play、 record、stop這三個功能。我們將Mp3產品座位一個組件的時候就不需要知道它的具體實現,只要看到接口定義知道這個對象有3個功能就可以使用了。那麼類似下面這樣的業務就完全可以在任何時間從3個品牌擴展到任意個品牌,開個玩笑的說,項目經理高高在上的寫完10個接口裡的方法聲明,然後就丟給手下的程序員去寫裡面的細節,由於接口已經統一(即每個方法傳入和傳出的格式已經統一),經理只需關注全局的業務就可以天天端杯咖啡走來走去了:
public Mp3 create();
public void copy(Mp3 mp3);
public Mp3 getMp3();
最後用一個簡單的例子說明接口:一個5號電池的手電筒,可以裝入任何牌子的5號電池,只要它符合5號電池的規范,裝入之後任何看不到是什麼牌子,只能感受到手電筒在完成它的功能。那麼生產手電筒的廠商和生產5號電池的廠商就可以完全解除依賴關系,可以各自自由開發自己的產品,因為它們都遵守5號電池應有的形狀、正負極位置等約定。這下大家能對接口多一點體會了麼?
2.組件和容器
針對接口是筆者特意強調的J2ee學習之路必備的思想,另外一個就是比較常規的組件和容器的概念了。很多教材和專業網站都說J2EE的核心是一組規范與指南,強調J2ee的核心概念就是組件+容器,這確實是無可厚非的。隨著越來越多的J2ee框架出現,相應的每種框架都一般有與之對應的容器。
容器,是用來管理組件行為的一個集合工具,組件的行為包括與外部環境的交互、組件的生命周期、組件之間的合作依賴關系等等。J2ee包含的容器種類大約有 Web容器、Application Client容器、EJB容器、Applet客戶端容器等。但在筆者看來,現在容器的概念變得有點模糊了,大家耳熟能詳是那些功能強大的開源框架,比如 Hibernate、Struts2、Spring、JSF等,其中Hibernate就基於JDBC的基礎封裝了對事務和會話的管理,大大方便了對數據庫操作的繁瑣代碼,從這個意義上來說它已經接近容器的概念了,EJB的實體Bean也逐漸被以Hibernate為代表的持久化框架所取代。
組件,本意是指可以重用的代碼單元,一般代表著一個或者一組可以獨立出來的功能模塊,在J2ee中組件的種類有很多種,比較常見的是EJB組件、DAO組件、客戶端組件或者應用程序組件等,它們有個共同特點是分別會打包成。war,。jar,。jar,。ear,每個組件由特定格式的xml描述符文件進行描述,而且服務器端的組件都需要被部署到應用服務器上面才能夠被使用。
稍微理解完組件和容器,還有一個重要的概念就是分層模型,最著名的當然是MVC三層模型。在一個大的工程或項目中,為了讓前台和後台各個模塊的編程人員能夠同時進行工作提高開發效率,最重要的就是實現層與層之間的耦合關系,許多分層模型的宗旨和開源框架所追求的也就是這樣的效果。在筆者看來,一個完整的 Web項目大概有以下幾個層次:
a)表示層(Jsp、Html、Javascript、Ajax、Flash等等技術對其支持)
b)控制層(Struts、JSF、WebWork等等框架在基於Servlet的基礎上支持,負責把具體的請求數據(有時卸載重新裝載)導向適合處理它的模型層對象)
c)模型層(筆者認為目前最好的框架是Spring,實質就是處理表示層經由控制層轉發過來的數據,包含著大量的業務邏輯)
d)數據層(Hibernate、JDBC、EJB等,由模型層處理完了持久化到數據庫中)
當然,這僅僅是筆者個人的觀點,僅僅是供大家學習做一個參考,如果要實現這些層之間的完全分離,那麼一個大的工程,可以僅僅通過增加人手就來完成任務。雖然《人月神話》中已經很明確的闡述了增加人手並不能是效率增加,很大程度上是因為彼此做的工作有順序上的依賴關系或者說難度和工作量上的巨大差距。當然理想狀態在真實世界中是不可能達到的,但我們永遠應該朝著這個方向去不斷努力。最開始所提倡的針對接口來編程,哪怕是小小的細節,寫一條List list= = new ArrayList()語句也能體現著處處皆使用接口的思想在裡面。Anyway,這只是個開篇,筆者會就自己用過的J2ee技術和框架再細化談一些經驗