以下內(nèi)容含腳本,或可能導(dǎo)致頁面不正常的代碼 |
---|
說明:上面顯示的是代碼內(nèi)容。您可以先檢查過代碼沒問題,或修改之后再運(yùn)行. |
以下內(nèi)容含腳本,或可能導(dǎo)致頁面不正常的代碼 |
---|
說明:上面顯示的是代碼內(nèi)容。您可以先檢查過代碼沒問題,或修改之后再運(yùn)行. |
(2)主要Java開源軟件的種類
JavaWeb容器: Tomcat、Resin
EJB容器: JBoss
框架: Java Web框架(Struts)、業(yè)務(wù)邏輯層框架(Spring)
持久化層: DAO、ORM映射工具(如Hibernate、OJB)
工程管理工具:ANT、Eclipse
日志輸出工具: Log4J
JavaWeb服務(wù)工具:Apache Axis
促成Java世界如此絢麗多姿的基本動力在于以下核心思想:
接口與實(shí)現(xiàn)
不同的軟件系統(tǒng)之間通過接口來交互。軟件系統(tǒng)只對外公開接口,封裝實(shí)現(xiàn)細(xì)節(jié)。接口描述了軟件系統(tǒng)具備的功能,也就是指定軟件系統(tǒng)能夠做什么,但是沒有指明怎么去做。接口具有三大作用:
(1)對于接口制訂者:SUN公司通過定義接口,來制定新的軟件系統(tǒng)的規(guī)范,例如Servlet規(guī)范、EJB規(guī)范和JDO規(guī)范,這些規(guī)范主要以接口的形式描述了軟件系統(tǒng)必須具備的功能。通過制定規(guī)范,SUN公司指引著Java技術(shù)的發(fā)展方向,同時給接口的實(shí)現(xiàn)者提供了自由發(fā)揮的廣闊空間。
(2)對于接口實(shí)現(xiàn)者:接口實(shí)現(xiàn)者以特定的方式實(shí)現(xiàn)標(biāo)準(zhǔn)的規(guī)范。例如一些開放源代碼軟件,如Tomcat和Resin分別以不同的實(shí)現(xiàn)方式,實(shí)現(xiàn)了標(biāo)準(zhǔn)的Servlet規(guī)范。同一個接口允許有多種實(shí)現(xiàn),使得Java領(lǐng)域保持著百花齊放、百家爭鳴的良好勢頭,
(3)對于接口調(diào)用者:接口調(diào)用者的程序具有良好的可移植性。以JavaWeb應(yīng)用為例,由于Tomcat和Resin遵守同樣的規(guī)范,因此用戶開發(fā)的JavaWeb應(yīng)用能夠順利的從Tomcat容器移植到Resin容器中。
封裝與抽象
封裝指的是在一個大系統(tǒng)中包含一個小系統(tǒng),大系統(tǒng)是建立在已有小系統(tǒng)的基礎(chǔ)上的更為復(fù)雜、功能更強(qiáng)大的系統(tǒng)。例如,Hibernate對JDBC API進(jìn)行了封裝,在Hibernate內(nèi)部依賴JDBC API來操縱數(shù)據(jù)庫,但是Hibernate API比JDBC API具有更強(qiáng)大的功能,例如JDBC API只具有連接和操縱數(shù)據(jù)庫的功能,而Hibernate不僅具備這一功能,還具有對象-關(guān)系映射的功能。
抽象是指從已經(jīng)存在的具有相似功能、但不同接口的系統(tǒng)中抽取共性,提煉出統(tǒng)一的接口。例如,Hibernate Transaction API是對JDBC
Transaction API和Java Transaction API(JTA)的抽象。
繼承與擴(kuò)展
繼承與擴(kuò)展是一對孿生兄弟,當(dāng)兩個類之間存在繼承關(guān)系,那么必定也存在擴(kuò)展關(guān)系。繼承的優(yōu)點(diǎn)在于提高代碼的可重用性,子類會繼承父類的所有public和protected類型的屬性和方法,在子類的程序代碼中,無需重復(fù)定義這些屬性和方法。擴(kuò)展的優(yōu)點(diǎn)在于使軟件應(yīng)用具有可伸縮性,能夠在已有功能的基礎(chǔ)上擴(kuò)展新的功能。
Struts框架充分運(yùn)用了擴(kuò)展思想。Struts框架中的許多類都是供應(yīng)用程序擴(kuò)展的,其中最主要的一個是Action類,在Action類中已經(jīng)定義了一些通用的方法,采用Struts框架的JavaWeb應(yīng)用將擴(kuò)展Action類,創(chuàng)建負(fù)責(zé)特定流程或業(yè)務(wù)的客戶化的Action類。
對象的生命周期
當(dāng)一個對象通過new語句創(chuàng)建后,它就會擁有一塊固定的內(nèi)存空間,如果沒有任何變量引用它,它就會結(jié)束生命周期,它占用的內(nèi)存空間隨時可能被JVM的垃圾回收器回收。
應(yīng)用程序如何管理對象的生命周期呢?目前比較流行的做法是把對象存放在一個“范圍”內(nèi)。例如在JavaWeb應(yīng)用中,JavaBean可以存放在request、session或application范圍內(nèi)。每個范圍對應(yīng)一個對象,例如request范圍對應(yīng)HttpServletRequest對象,session范圍對應(yīng)HttpSession對象,application范圍對應(yīng)ServletContext對象。把一個JavaBean存放在request范圍內(nèi),實(shí)質(zhì)上是在HttpServletRequest對象的一個集合屬性中加入這個JavaBean的引用,這個集合屬性也被稱為HttpServletRequest對象的緩存。
把一個JavaBean存放在request范圍內(nèi),等價于以下兩種說法:
把一個JavaBean加入到HttpServletRequest對象的緩存中
把一個JavaBean和HttpServletRequest對象關(guān)聯(lián)
當(dāng)JavaBean位于request范圍內(nèi),這個JavaBean的生命周期依賴于HttpServletRequest對象的生命周期,當(dāng)HttpServletRequest對象結(jié)束生命周期,并且這個JavaBean也不被應(yīng)用程序中的其他變量引用,那么它就會結(jié)束生命周期。
那么HttpServletRequest對象本身的生命周期由誰管理呢?這是由JavaWeb容器(也稱Servlet容器)來管理的。對于每個HTTP請求,JavaWeb容器會自動創(chuàng)建一個HttpServletRequest對象,當(dāng)HTTP請求的響應(yīng)完畢,JavaWeb容器就會結(jié)束這個對象的生命周期。同理,當(dāng)每個HTTP會話開始,JavaWeb容器會自動創(chuàng)建一個HttpSession對象,當(dāng)這個會話結(jié)束,JavaWeb容器就會結(jié)束這個對象的生命周期;當(dāng)每個JavaWeb應(yīng)用啟動時,JavaWeb容器會自動創(chuàng)建一個ServletContext對象,當(dāng)這個應(yīng)用被關(guān)閉,JavaWeb容器就會結(jié)束這個對象的生命周期。
在Hibernate中,在net.sf.hibernate.Session范圍內(nèi)加入一個持久化對象,實(shí)質(zhì)上是在Session對象的集合屬性中加入這個持久化對象的引用。以下幾種說法是等價的:
在Session范圍內(nèi)加入一個持久化對象
在Session的緩存中加入一個持久化對象
把一個持久化對象與Session關(guān)聯(lián)
值得注意的是,Hibernate的Session不僅能管理緩存中持久化對象的生命周期,還會負(fù)責(zé)按照持久化對象的狀態(tài)的變化,來同步更新數(shù)據(jù)庫。
集成開源軟件的基本步驟
在開發(fā)Java應(yīng)用時,為了提高開發(fā)效率,縮短開發(fā)周期,常常需要集成第三方提供的Java軟件,如ORM映射工具Hibernate、MVC框架Struts、日志工具Log4J和Web服務(wù)軟件Apache
AXIS等。在自己的應(yīng)用中集成這些第三方軟件時,大體步驟都很相似。
(1) 把它們的JAR文件拷貝到classpath中。
(2) 創(chuàng)建它們的配置文件(XML格式的文件或者Java屬性文件),這些配置文件通常也位于classpath中。
(3) 在程序中訪問它們的接口。
接口與配置文件,是軟件系統(tǒng)對外公開的兩個主要窗口。無論是Tomcat、Struts還是Hibernate,都離不開配置文件,與編寫程序代碼相比,配置文件能提高軟件的可維護(hù)性,更加靈活的適應(yīng)用戶變化的需求,但是,配置文件不擅長表達(dá)非常復(fù)雜的邏輯,在這種情況下,必須求助于程序代碼。作為軟件使用者,如果僅僅想快速掌握一個新的Java軟件的使用方法,而不打算深入了解軟件內(nèi)在原理和結(jié)構(gòu),無非就是了解它的接口以及配置文件的使用方法。當(dāng)然,如果想對軟件的運(yùn)用達(dá)到得心應(yīng)手的地步,還應(yīng)該了解軟件本身的實(shí)現(xiàn)原理和結(jié)構(gòu),而這些軟件無非就是通過抽象、封裝和實(shí)現(xiàn)等手段,從簡單的小系統(tǒng)出發(fā),構(gòu)造出更加復(fù)雜,但是對外有著簡潔統(tǒng)一的接口的大系統(tǒng)
下面為避免混淆,在文中凡未加特殊說明的Java,統(tǒng)指桌面Java而言。
一、 問題提出
*常用的解釋性Java(Java Applet)的執(zhí)行速度慢,不適于嵌入式的應(yīng)用。
*Java要求過大的內(nèi)存。
*嵌入式設(shè)備要求操作硬件。因Java廢棄了C語言所使用的指針,且在Web環(huán)境下使用了Java虛擬機(jī)(JVM),使Java無力直接甚至間接地用指針操作硬件。
*Java使用一些自動功能會引起執(zhí)行時間的不確定性,成為嵌入式的大忌。如垃圾自動收集器。本是對于C的重大改進(jìn),但卻因程序自動地回收垃圾,從而引入了實(shí)時的時間不確定性。
二、解決方案
使用AOT編譯器
為解決解釋性Java(Java Applet)執(zhí)行速度過慢的問題,發(fā)展了AOT(ahead-of-time)編譯器。大家喜歡在Internet上使用Java的一個原因是其字節(jié)碼具有跨平臺性,即同一Java代碼可以運(yùn)行于PC、Mac、Solaris,甚至于主機(jī)之上。為此,在英文叫它WORA(寫一次即可通行于任意機(jī))。這是因?yàn)槊恳徊僮飨到y(tǒng)平臺上都有符合自己機(jī)型的專用Java虛擬機(jī)(JVM),由它對字節(jié)碼進(jìn)行解釋運(yùn)行。因?yàn)榻忉尦绦蛐柘缺唤忉屧俦粓?zhí)行,多了解釋環(huán)節(jié),延誤數(shù)秒鐘時間。如果是撥打電話,這個時間足以令人生厭,F(xiàn)在使用AOT(ahead-of-time)超前編譯器,提前將解釋碼轉(zhuǎn)換為本平臺所用的并經(jīng)優(yōu)化過的二進(jìn)制碼,速度提高很多,F(xiàn)有Cygnus公司聲稱,它開發(fā)的AOT編譯器執(zhí)行速度是原解釋程序的8倍。NewMonics說它的 QuickPERC編譯器是原解釋程序的20倍。當(dāng)然,AOT編譯器也有不足,就是他犧牲了Java的WORA。
減少內(nèi)存的占用
所有的面向?qū)ο笳Z言,比C及匯編語言點(diǎn)用內(nèi)存都多。這個問題對于桌面系統(tǒng)早已不再是考慮的因素了,如服務(wù)器平均占用數(shù)GB的內(nèi)存已司空見慣。但是,對于嵌入式系統(tǒng)卻不能不考慮。用Java開發(fā)的信息家電產(chǎn)品可能需要把內(nèi)存限制到512KB以下。如果嵌入式系統(tǒng)使用的是規(guī)模為1MB的核心類庫,那就是說,一句代碼尚未寫,內(nèi)存早就不夠用了。
為此,需要把用不到的類、類方法和代統(tǒng)統(tǒng)從程序中剔除。(AOT超前編譯器可以幫助解決這個問題。)再就是自己開發(fā)本平臺專用的,既短小高效、又符合Java API標(biāo)準(zhǔn)的Java核心類庫。
開發(fā)能混合編程的IDE
一般認(rèn)為,用C語言寫的程序,指鍺使用不當(dāng)引起的缺陷占總?cè)毕莸?0%左右。Java語言,出于安全的考慮,才廢棄了使用指針。但是,指針卻能夠最直接地訪問到存儲器和真實(shí)的硬件,F(xiàn)在,為在嵌入式Java中能夠訪問到硬件,不得不改用本地接口,即從嵌入式Java中利用能夠訪問到硬件的C語言函數(shù)來實(shí)行交叉編程。這就意味著增加了復(fù)雜性。開發(fā)人員需要具備多語言以及多層次的混合編程和混合調(diào)試的能力。發(fā)展多語言多層次混合編程的IDE,無疑十分有助于一般開發(fā)人員完成這一相當(dāng)復(fù)雜的課題。Metrowerks的CodeWorrior和IBM的VisualAge就是新開發(fā)的基于J2ME的這樣的IDE。
克服時間的不確定性
Java 最主要的問題是時間不確定性,主要來源于存儲器殘渣的自動收集再生器。這種垃圾收集再生器工作的時候,自動地決定何時停下其他程序的執(zhí)行,再根據(jù)當(dāng)時殘渣的實(shí)際情況或長或短地完成任務(wù)。所以,它嚴(yán)重地干擾實(shí)時應(yīng)用所要求的時間確定性。為解決這一問題,不同公司采用不同的方法和垃圾收集的算法。 NewMonics的Real Time Executives和Windriver的FastJ都是保證絕對的確定時間,Sun公司用不同的辦法但也保證具有實(shí)時的確定性。采用不同的編程技巧,譬如使用類型確定的線程局部存儲,也可以避免因垃圾收集引發(fā)的沖突。
需保持跨平臺的必要
AOT 編譯器生成的Java代碼喪失了Java在其他操作平臺上的執(zhí)行能力。要想把Java的源代碼再向其他平臺移植,需要附加很大的勞動。面向?qū)ο蟮囊粋基本設(shè)計原理就是只要保持接品不變,那么,與接口交談的代碼在移植時就不受影響。所謂高級邏輯接口的隔離手法,事實(shí)上,就是將平臺敏感的內(nèi)容同移值無關(guān)的代碼分離開來,并且分別提供同樣功能的平臺敏感程序,F(xiàn)在,針對嵌入式Java,目前還沒有人做這項工作。
三、實(shí)際應(yīng)用
Java是良好的嵌入式編程語言嗎?
還不能這么說,至少現(xiàn)在是這樣。因?yàn)樵谇度胧较到y(tǒng)中,Java如何應(yīng)用要看具體情況而定。對于需要管理中斷來完成重要任務(wù)的應(yīng)用系統(tǒng),就不宜于選用Java 進(jìn)行開發(fā),譬如引導(dǎo)登外星的飛行器系統(tǒng)就是這樣。對于要求輕型、高效、任務(wù)重要、時間確定性要求極高的系統(tǒng),也是只能局限于使用C語言和匯編。比如,點(diǎn)燃登陸外星的制動火箭系統(tǒng),定時通過串行口獲取關(guān)鍵信息一邊做出決定的系統(tǒng),定時報告航天器方位的系統(tǒng)等都不能使用Java。但是,需要不斷與他人通信聯(lián)系,以便對貨運(yùn)進(jìn)行有效管理的手持系統(tǒng),又最適合使用Java編程。因?yàn),它既發(fā)揚(yáng)了Java Applet固有的跨平臺應(yīng)用地Web環(huán)境的特點(diǎn),又能充分利用服務(wù)器端的現(xiàn)成軟件。
使用Java有時也并不完全取決于技術(shù)
立足于經(jīng)濟(jì)上的考慮,比單獨(dú)的技術(shù)考慮更為重要。譬如,對于服務(wù)器,為了支持使用Java,寧愿多花費(fèi)數(shù)千元擴(kuò)大存儲器是正確的。因?yàn),從投?產(chǎn)出的分析也得出同樣的結(jié)論。又如手機(jī),若為支持使用Java,哪性僅只需要多花一元錢去擴(kuò)大存儲器也是不可行的。因?yàn)椋謾C(jī)的生產(chǎn)是以行百萬件的產(chǎn)量來考慮的,多花一元線,就意味著多花千百萬元,諾大的數(shù)字遠(yuǎn)比技術(shù)的先進(jìn)更為重要,是顯而易見的。
實(shí)施嵌入式Java時需注意
Java 用于嵌入式還是瓣生事物,需要探路前進(jìn),摸著石頭過河,忌冒進(jìn)和全面開花。應(yīng)試探性地從使用現(xiàn)成的嵌入式J2ME開始,在它的通用性的開發(fā)環(huán)境下運(yùn)行本平臺的字節(jié)碼。盡可能地順著J2MME向前走,盡可能地順著J2ME向前走,盡可能地走得遠(yuǎn)一點(diǎn),只有在遇到特殊問題時才導(dǎo)求新的解決辦法。新方法的采用并不一定能夠解決問題,比如,AOT或半自動的垃圾收集器等可能并沒有解決你的問題,也勿驚慌,要總結(jié)經(jīng)驗(yàn)做出評價,繼續(xù)前進(jìn),使嵌入式Java日罄完善。
要重視IDE的選用,好的IDE絕對是良好的助手。否則,你是單槍匹馬,披荊斬棘,艱苦良多。
]]>軟件是有生命的,這可能是老調(diào)重彈了,但是因?yàn)樗玛P(guān)分層架構(gòu)的原由,反復(fù)強(qiáng)調(diào)都不過分。
一個有生命的軟件首先必須有一個靈活可擴(kuò)展的基礎(chǔ)架構(gòu),其次才是完整的功能。
目前很多人對軟件的思想還是焦點(diǎn)落在后者:完整的功能,覺得一個軟件功能越完整越好,其實(shí)關(guān)鍵還是架構(gòu)的靈活性,就是前者,基礎(chǔ)架構(gòu)好,功能添加只是時間和工作量問題,但是如果架構(gòu)不好,功能再完整,也不可能包括未來所有功能,軟件是有生命的,在未來成長時,更多功能需要加入,但是因?yàn)榛A(chǔ)架構(gòu)不靈活不能方便加入,死路一條。
正因?yàn)槠胀ㄈ藢浖嬖诙桃曊`區(qū),對功能追求高于基礎(chǔ)架構(gòu),很多吃了虧的老程序員就此離開軟件行業(yè),帶走寶貴的失敗經(jīng)驗(yàn),新的盲目的年輕程序員還是使用老的思維往前沖。其實(shí)很多國外免費(fèi)開源框架如ofbiz compiere和slide也存在這方面陷阱,貌似非常符合胃口,其實(shí)類似國內(nèi)那些幾百元的盜版軟件,擴(kuò)展性以及持續(xù)發(fā)展性嚴(yán)重不足。
那么選擇現(xiàn)在一些流行的框架如Hibernate、Spring/Jdonframework是否就表示基礎(chǔ)架構(gòu)打好了呢?其實(shí)還不盡然,關(guān)鍵還是取決于你如何使用這些框架來搭建你的業(yè)務(wù)系統(tǒng)。
存儲過程和復(fù)雜SQL語句的陷阱
首先談?wù)劥鎯^程使用的誤區(qū),使用存儲過程架構(gòu)的人以為可以解決性能問題,其實(shí)它正是導(dǎo)致性能問題的罪魁禍?zhǔn)字,打個比喻:如果一個人頻臨死亡,打一針可以讓其延長半年,但是打了這針,其他所有醫(yī)療方案就全部失效,請問你會使用這種短視方案嗎?
為什么這樣說呢?如果存儲過程都封裝了業(yè)務(wù)過程,那么運(yùn)行負(fù)載都集中在數(shù)據(jù)庫端,要中間J2EE應(yīng)用服務(wù)器干什么?要中間服務(wù)器的分布式計算和集群能力做什么?只能回到過去集中式數(shù)據(jù)庫主機(jī)時代。現(xiàn)在軟件都是面向互聯(lián)網(wǎng)的,不象過去那樣局限在一個小局域網(wǎng),多用戶并發(fā)訪問量都是無法確定和衡量,依靠一臺數(shù)據(jù)庫主機(jī)顯然是不能夠承受這樣惡劣的用戶訪問環(huán)境的。(當(dāng)然搞數(shù)據(jù)庫集群也只是五十步和百步的區(qū)別)。
從分層角度來看,現(xiàn)在三層架構(gòu):表現(xiàn)層、業(yè)務(wù)層和持久層,三個層次應(yīng)該分割明顯,職責(zé)分明:持久層職責(zé)持久化保存業(yè)務(wù)模型對象,業(yè)務(wù)層對持久層的調(diào)用只是幫助我們激活曾經(jīng)委托其保管的對象,所以,不能因?yàn)槌志脤邮潜9苷撸覀兙鸵云錇楹诵膰@其編程,除了要求其歸還模型對象外,還要求其做其做復(fù)雜的業(yè)務(wù)組合。打個比喻:你在火車站將水果和盤子兩個對象委托保管處保管,過了兩天來取時,你還要求保管處將水果去皮切成塊,放在盤子里,做成水果盤給你,合理嗎?
上面是談過分依賴持久層的一個現(xiàn)象,還有一個正好相反現(xiàn)象,持久層散發(fā)出來,開始擠占業(yè)務(wù)層,腐蝕業(yè)務(wù)層,整個業(yè)務(wù)層到處看見的是數(shù)據(jù)表的影子(包括數(shù)據(jù)表的字段),而不是業(yè)務(wù)對象。這樣程序員應(yīng)該多看看OO經(jīng)典PoEAA。PoEAA 認(rèn)為除了持久層,不應(yīng)該在其他地方看到數(shù)據(jù)表或表字段名。
當(dāng)然適量使用存儲過程,使用數(shù)據(jù)庫優(yōu)點(diǎn)也是允許的。按照Evans DDD理論,可以將SQL語句和存儲過程作為規(guī)則Specification一部分。
Hibernate等ORM問題
現(xiàn)在使用Hibernate人也不少,但是他們發(fā)現(xiàn)Hibernate性能緩慢,所以尋求解決方案,其實(shí)并不是 Hibernate性能緩慢,而是我們使用方式發(fā)生錯誤:
“最近本人正搞一個項目,項目中我們用到了struts1.2+hibernate3, 由于關(guān)系復(fù)雜表和表之間的關(guān)系很多,在很多地方把lazy都設(shè)置false,所以導(dǎo)致數(shù)據(jù)一加載很慢,而且查詢一條數(shù)據(jù)更是非常的慢!
Hibernate是一個基于對象模型持久化的技術(shù),因此,關(guān)鍵是我們需要設(shè)計出高質(zhì)量的對象模型,遵循DDD領(lǐng)域建模原則,減少降低關(guān)聯(lián),通過分層等有效辦法處理關(guān)聯(lián)。如果采取圍繞數(shù)據(jù)表進(jìn)行設(shè)計編程,加上表之間關(guān)系復(fù)雜(沒有科學(xué)方法處理、偵察或減少這些關(guān)系),必然導(dǎo)致 系統(tǒng)運(yùn)行緩慢,其實(shí)同樣問題也適用于當(dāng)初對EJB的實(shí)體Bean的CMP抱怨上,實(shí)體Bean是Domain Model持久化,如果不首先設(shè)計Domain Model,而是設(shè)計數(shù)據(jù)表,和持久化工具設(shè)計目標(biāo)背道而馳,能不出問題嗎?關(guān)于這個問題N多年就在Jdon爭論過。
關(guān)于本系列
PHP 是一種非常優(yōu)秀的 Web 開發(fā)語言,而在商業(yè)應(yīng)用程序開發(fā)方面,Java 編程語言十分流行。因此,為了在 AIX Version 5.3 操作系統(tǒng)上充分利用它們的優(yōu)勢,專門開發(fā)了 PHP Java Bridge。本系列文章向 AIX 5.3 開發(fā)人員介紹了如何在他們的 Web 應(yīng)用程序開發(fā)中集成 PHP 和 Java 技術(shù)。
為了說明這一點(diǎn),您將按照典型的開發(fā)過程來構(gòu)建一個簡單的問卷調(diào)查應(yīng)用程序,具體內(nèi)容包括:
開發(fā)主要的 Java 應(yīng)用程序
通過 Servlet 將 Java 應(yīng)用程序公開為基于 Java 的 Web 應(yīng)用程序
添加在數(shù)據(jù)庫中存儲信息的支持
將原始應(yīng)用程序公開為 Web Services,并為該應(yīng)用程序提供 PHP 接口
使用專門的 PHP Java Bridge 重新開發(fā) PHP 接口
本系列文章共分為六個部分:
第 1 部分介紹了一個應(yīng)用程序,并為構(gòu)建 Java 應(yīng)用程序以及使用 Tomcat 執(zhí)行基于 Java 的 Web 應(yīng)用程序搭建了相應(yīng)的環(huán)境。
第 2 部分介紹了主要的應(yīng)用程序代碼以及一個簡單的 Java Servlet 的開發(fā),以便為信息提供一個 Web 接口。
第 3 部分將核心應(yīng)用程序連接到 DB2? 數(shù)據(jù)庫,以便對問卷調(diào)查的問題和回答進(jìn)行存儲。
第 4 部分對原始應(yīng)用程序進(jìn)行轉(zhuǎn)換,使其能夠作為 Web Services 進(jìn)行訪問,并且它為 PHP 接口提供了基礎(chǔ)。
第 5 部分使用 PHP Java Bridge 為 Java 應(yīng)用程序構(gòu)建 PHP 接口。
第 6 部分對這個應(yīng)用程序進(jìn)行重新開發(fā),以便使用 PHP Java Bridge 來代替 Web Services 接口。
關(guān)于本教程
本教程是這個系列文章的最后一個部分,在本教程中,您將了解如何組合使用 PHP 和 Java 技術(shù),以便為支持問卷調(diào)查應(yīng)用程序的原始 Java 類構(gòu)建 Web 接口。這個最終解決方案使用 PHP Java Bridge 以使得您可以為在本系列文章的前面幾個部分中所開發(fā)的 Java 類構(gòu)建基于 PHP 的接口。
您首先將了解 PHP Java Bridge、以及它的操作與最初開發(fā)的 Web 服務(wù)方法之間的區(qū)別,從而對這幾種不同的技術(shù)進(jìn)行比較。然后,在研究原始 Java 類的 PHP 接口的最終備選方法之前,您將研究幾種不同的集成您的基于 PHP 和 Java 的解決方案。
先決條件
為了學(xué)習(xí)本教程,您需要安裝下列軟件:
IBM pSerIEs? 服務(wù)器(本文中的代碼使用 AIX Version 5.3 進(jìn)行了測試。)
Apache Tomcat 系統(tǒng)
Eclipse IDE
Java 5 64-bit SDK(要下載這個包,您需要進(jìn)行注冊,但注冊是免費(fèi)的。)
Mozilla Web browser for AIX
幾種不同連接技術(shù)的比較
問卷調(diào)查應(yīng)用程序所使用的 Web 服務(wù)方法為您提供了極大的靈活性,而 PHP Java Bridge 以不同的方式提供了類似的靈活性。在您更深入地研究開發(fā)過程之前,讓我們更仔細(xì)地分析一下它們之間的區(qū)別和相似之處。
Web 服務(wù)方法
您對原始應(yīng)用程序進(jìn)行了轉(zhuǎn)換,這樣一來,在本系列文章的第四部分中(請參見參考資料),就可以將其作為 Web Services 進(jìn)行訪問。除了可訪問性之外,Web Services 模型還具有許多其它的優(yōu)點(diǎn)。通過 Web Services 接口來公開類,您可以保證互操作性,因?yàn)閹缀跛械恼Z言都支持某些形式的 Web Services ,無論是 XML-RPC 還是簡單對象訪問協(xié)議 (SOAP)。
這也就帶來了極大的靈活性,F(xiàn)在,您的 Java 后端可以由采用 C、Perl、Java 語言、PHP、JavaScript 和許多其他編程語言所編寫的腳本和應(yīng)用程序來進(jìn)行訪問;然而,實(shí)現(xiàn)互操作性是要付出一定代價的。
正如您在本系列文章的第四部分中所看到的,將您的應(yīng)用程序公開為 Web Services 是一項復(fù)雜的任務(wù)。要正確地完成這項工作,需要通過 Web 服務(wù)描述語言 (WSDL) 文件開發(fā)和部署您的代碼;然后,您必須單獨(dú)地為每個函數(shù)定義不同的接口,同時還需要確保采用與您希望使用的標(biāo)準(zhǔn)可互操作的格式,對所提供的值和返回的值進(jìn)行編碼和封裝。
在您為核心類開發(fā)和添加新的功能和擴(kuò)展時,所有的這些工作都需要花費(fèi)大量的時間進(jìn)行開發(fā)、以及較長的時間進(jìn)行控制。要使得原始類能夠通過 Web 服務(wù)接口進(jìn)行訪問,可能會使得您的開發(fā)時間增加 20% 到 50%。
而且,正如稍后將更詳細(xì)地進(jìn)行介紹的,Web 服務(wù)方法還隱含了不容忽視的顯著性能開銷(如果您希望在大型操作環(huán)境中部署該應(yīng)用程序的話)。
PHP Java Bridge
在本系列文章的第五部分中,您詳細(xì)地了解了 PHP Java Bridge(請參見參考資料),但是 PHP Java Bridge 的關(guān)鍵元素允許您直接從 PHP 內(nèi)部訪問 Java 類,就好像您正在訪問本地 PHP 類一樣。
盡管 Web 服務(wù)和 PHP Java Bridge 接口在本質(zhì)上存在很大的差別,但事實(shí)上,它們都使用 XML 進(jìn)行通信,以交換有關(guān)原始方法和類、以及應(yīng)該如何對它們進(jìn)行訪問的信息。與 Web 服務(wù)解決方案有所不同,這個過程是自動的。
正如您在第五部分中所看到的(請參見參考資料)、以及本文清單 1 中所介紹的,在您導(dǎo)入 PHP 元素、并且創(chuàng)建到遠(yuǎn)程 Java 主機(jī)的連接之后,使用和創(chuàng)建 Java 類和對象是非常簡單的。
清單 1. 簡單的 PHP Java Bridge 的示例 <? require_once("http://sulaco.mcslp.pri:8080/JavaBridge/java/Java.inc"); $System = new Java("java.lang.System"); print_r($System->getProperties); ?> |
在本教程后面的內(nèi)容中,您將研究所需的確切的方法和解決方案。
區(qū)別和相似之處
Web Services 和 PHP Java 解決方案之間存在許多明顯的區(qū)別和相似之處,從而使得采用這兩種方法開發(fā)和部署應(yīng)用程序時具有相應(yīng)的優(yōu)點(diǎn)和缺點(diǎn)。
例如,Web 服務(wù)和 PHP Java Bridge 解決方案都允許您使用 PHP 作為前端、使用 Java 環(huán)境作為應(yīng)用程序的后端部分。對于 Web 服務(wù)解決方案,您必須開發(fā)原始類、Web 服務(wù)類和 PHP 接口。對于 PHP Java Bridge,您只需要開發(fā)原始 Java 類和 PHP 前端,PHP Java Bridge 可以為您處理所有的互操作性問題。
在 Web 服務(wù)和 PHP Java Bridge 解決方案之間還存在一個比較顯著的區(qū)別,即完成解決方案所需的步驟有所不同。Web 服務(wù)解決方案需要額外的開發(fā)時間,以使用所需的 Web 服務(wù)接口來公開服務(wù)、并使得它們可供使用。在 PHP 中使用 Web 服務(wù)也是相當(dāng)繁瑣的,因?yàn)槟仨氶_發(fā)一個能夠?yàn)橐验_發(fā)的 Web 服務(wù)接口提供接口的解決方案。
對于 PHP Java Bridge,您可以直接訪問現(xiàn)有的 Java 類,而不必在 Java 端顯式地開發(fā)接口、或者在 PHP 端顯式地開發(fā)訪問接口。
性能
為了將您的原始請求轉(zhuǎn)換為完全與平臺無關(guān)的形式,使用 Web 服務(wù)的關(guān)鍵問題之一是必須將請求轉(zhuǎn)換為 XML。所得到的 XML 數(shù)據(jù)包中包括請求、源或目標(biāo)信息、以及請求中所包含的任何數(shù)據(jù)或者信息(例如,方法或函數(shù)的參數(shù)),這使得 XML 組件的負(fù)載變得非常大。
采用這種方式生成有效的 XML 是相當(dāng)花費(fèi)時間的,但是對該信息進(jìn)行解碼甚至可能需要花費(fèi)更多的時間,因?yàn)?XML 解析的過程并不像您所預(yù)期的那么簡單和直接。和發(fā)送請求到服務(wù)器的客戶端的負(fù)載相比,這個處理過程會呈現(xiàn)更高的負(fù)載,隨后還會有接受請求和最后處理請求的過程。在將響應(yīng)發(fā)送回客戶端的時候,將按相反的順序執(zhí)行相同的處理過程(采用 XML 對響應(yīng)進(jìn)行編碼,發(fā)送到客戶端,客戶端解析 XML 并且提取響應(yīng))。
您可以在圖 1 中更詳細(xì)地看到這個過程。
圖 1. 實(shí)際應(yīng)用中的 Web 服務(wù)接口 ]]>一、ODBC到JDBC的發(fā)展歷程
說到JDBC,很容易讓人聯(lián)想到另一個十分熟悉的字眼ODBC。它們之間有沒有聯(lián)系呢?如果有,那么它們之間又是怎樣的關(guān)系呢?
ODBC是OpenDatabaseConnectivity的英文簡寫。它是一種用來在相關(guān)或不相關(guān)的管理系統(tǒng)(DBMS)中存取數(shù)據(jù)的,用C語言實(shí)現(xiàn)的,標(biāo)準(zhǔn)應(yīng)用程序數(shù)據(jù)接口。通過ODBCAPI,應(yīng)用程序可以存取保存在多種不同管理系統(tǒng)(DBMS)中的數(shù)據(jù),而不論每個DBMS使用了何種數(shù)據(jù)存儲格式和編程接口。
1.ODBC的結(jié)構(gòu)模型
ODBC的結(jié)構(gòu)包括四個主要部分:應(yīng)用程序接口、驅(qū)動器管理器、驅(qū)動器和數(shù)據(jù)源。
應(yīng)用程序接口:屏蔽不同的ODBC驅(qū)動器之間函數(shù)調(diào)用的差別,為用戶提供統(tǒng)一的SQL編程接口。
驅(qū)動器管理器:為應(yīng)用程序裝載驅(qū)動器。
驅(qū)動器:實(shí)現(xiàn)ODBC的函數(shù)調(diào)用,提供對特定數(shù)據(jù)源的SQL請求。如果需要,驅(qū)動器將修改應(yīng)用程序的請求,使得請求符合相關(guān)的DBMS所支持的文法。
數(shù)據(jù)源:由用戶想要存取的數(shù)據(jù)以及與它相關(guān)的操作系統(tǒng)、DBMS和用于DBMS的網(wǎng)絡(luò)平臺組成。
雖然ODBC驅(qū)動器管理器的主要目的是加載驅(qū)動器,以便ODBC函數(shù)調(diào)用,但是驅(qū)動器本身也執(zhí)行ODBC函數(shù)調(diào)用,并與相互配合。因此當(dāng)應(yīng)用系統(tǒng)發(fā)出調(diào)用與數(shù)據(jù)源進(jìn)行連接時,驅(qū)動器能管理通信協(xié)議。當(dāng)建立起與數(shù)據(jù)源的連接時,驅(qū)動器便能處理應(yīng)用系統(tǒng)向DBMS發(fā)出的請求,對分析或發(fā)自數(shù)據(jù)源的設(shè)計進(jìn)行必要的翻譯,并將結(jié)果返回給應(yīng)用系統(tǒng)。
2.JDBC的誕生
自從Java語言于1995年5月正式公布以來,Java風(fēng)靡全球。出現(xiàn)大量的用java語言編寫的程序,其中也包括應(yīng)用程序。由于沒有一個Java語言的API,編程人員不得不在Java程序中加入C語言的ODBC函數(shù)調(diào)用。這就使很多Java的優(yōu)秀特性無法充分發(fā)揮,比如平臺無關(guān)性、面向?qū)ο筇匦缘。隨著越來越多的編程人員對Java語言的日益喜愛,越來越多的公司在Java程序開發(fā)上投入的精力日益增加,對java語言接口的的API的要求越來越強(qiáng)烈。也由于ODBC的有其不足之處,比如它并不容易使用,沒有面向?qū)ο蟮奶匦缘鹊龋琒UN公司決定開發(fā)一Java語言為接口的應(yīng)用程序開發(fā)接口。在JDK1.x版本中,JDBC只是一個可選部件,到了JDK1.1公布時,SQL類包(也就是JDBCAPI)就成為Java語言的標(biāo)準(zhǔn)部件。
二、JDBC技術(shù)概述
JDBC是一種可用于執(zhí)行SQL語句的JavaAPI(ApplicationProgrammingInterface,應(yīng)用程序設(shè)計接口)。它由一些Java語言寫的類、界面組成。JDBC給應(yīng)用開發(fā)人員、前臺工具開發(fā)人員提供了一種標(biāo)準(zhǔn)的應(yīng)用程序設(shè)計接口,使開發(fā)人員可以用純Java語言編寫完整的應(yīng)用程序。
通過使用JDBC,開發(fā)人員可以很方便地將SQL語句傳送給幾乎任何一種。也就是說,開發(fā)人員可以不必寫一個程序Sybase,寫另一個程序Oracle,再寫一個程序Microsoft的SQLServer。用JDBC寫的程序能夠自動地將SQL語句傳送給相應(yīng)的管理系統(tǒng)(DBMS)。不但如此,使用Java編寫的應(yīng)用程序可以在任何支持Java的平臺上運(yùn)行,不必在不同的平臺上編寫不同的應(yīng)用。Java和JDBC的結(jié)合可以讓開發(fā)人員在開發(fā)應(yīng)用時真正實(shí)現(xiàn)WriteOnce,RunEverywhere!
Java具有健壯、安全、易用等特性,而且支持自動網(wǎng)上下載,本質(zhì)上是一種很好的應(yīng)用的編程語言。它所需要的是Java應(yīng)用如何同各種各樣的連接,JDBC正是實(shí)現(xiàn)這種連接的關(guān)鍵。
JDBC擴(kuò)展了Java的能力,如使用Java和JDBCAPI就可以公布一個Web頁,頁中帶有能遠(yuǎn)端的Ap?plet;蛘咂髽I(yè)可以通過JDBC讓全部的職工(他們可以使用不同的操作系統(tǒng),如Windwos,Machintosh和UNIX)在In?tranet上連接到幾個全球上,而這幾個全球可以是不相同的。隨著越來越多的程序開發(fā)人員使用Java語言,對Java易操作性的需求越來越強(qiáng)烈。
MIS管理人員喜歡Java和JDBC,因?yàn)檫@樣可以更容易經(jīng)濟(jì)地公布信息。各種已經(jīng)安裝在中的事務(wù)處理都將繼續(xù)正常運(yùn)行,甚至這些事務(wù)處理是存儲在不同的管理系統(tǒng)中;而對新的應(yīng)用來說,開發(fā)時間將縮短,安裝和版本升級將大大簡化。程序員可以編寫或改寫一個程序,然后將它放在服務(wù)器上,而每個用戶都可以服務(wù)器得到最新的版本。對于信息服務(wù)行業(yè),Java和JDBC提供了一種很好的向外界用戶更新信息的方法。
1.JDBC的任務(wù)
簡單地說,JDBC能完成下列三件事:
1)同一個建立連接;
2)向發(fā)送SQL語句;
3)處理返回的結(jié)果。
]]>新技術(shù)采用概況
許多分析家擁有技術(shù)應(yīng)用所需的描述模型。其中最為流行的模型是定義在Ruby的Web開發(fā)框架Iowa中,用來描述農(nóng)產(chǎn)品的應(yīng)用,稍后在一本由Geoffrey A. Moore寫作的名為《跨越鴻溝》(Crossing the Chasm)的書中,被用來描述技術(shù)內(nèi)容。在書中,Moore分析了技術(shù)應(yīng)用周期中存在著的五個截然不同的群體:
技術(shù)專家。這個群體傾向于采用新的技術(shù)。任何一種有前途的技術(shù)都會引起這個群體的注意。
先行采納者。不管這項技術(shù)是否在主流技術(shù)中取得成功,這個群體都將會采用新的技術(shù)來提升競爭優(yōu)勢。
實(shí)用主義者。一旦新的技術(shù)進(jìn)入主流應(yīng)用,或是有足夠陡峭的增長曲線來保證技術(shù)將得到廣泛采用,那么實(shí)用主義者就會積極采用新的技術(shù)。
保守派。只有新技術(shù)成為必須的時候,他們才會考慮采用新的技術(shù)。
懷疑論者。這個群體可能很晚才會采用新的技術(shù),或者也可能永遠(yuǎn)只使用某一特定技術(shù)。
Moore指出,技術(shù)應(yīng)用的關(guān)鍵之處在于團(tuán)隊中是否存在實(shí)用主義者。因?yàn)閷?shí)用主義者需要新技術(shù)大規(guī)模的應(yīng)用,這個中間群體希望看到其他務(wù)實(shí)派在團(tuán)隊做出承諾之前就使用新的技術(shù)。這是一個類似于《第二十二條軍規(guī)》書中所描述的現(xiàn)象,因?yàn)閯?wù)實(shí)派們都會相互依賴的存在。出于這樣的原因,在先行采納者排列在技術(shù)專家之后和務(wù)實(shí)派之前,你會經(jīng)常在市場接受度曲線中看到一種下降的趨勢。Moore將這種下降稱之為鴻溝傾向,并且這種想法應(yīng)出于圍繞任何新技術(shù)的風(fēng)險討論的中心。
]]>
基于JVM的語言正在開始流行
當(dāng)Sun Microsystems公司在1995年第一次揭開Java的面紗的時候,就是非常難被定義的。這是因?yàn)镴AVA是由多個部分構(gòu)成:首先,它當(dāng)然是一個面向?qū)ο笳Z言。同時JAVA也是一個定義標(biāo)準(zhǔn)的語言(或多個標(biāo)準(zhǔn),包括移動設(shè)備,標(biāo)準(zhǔn),和企業(yè)三個版本)。最后,Java是一個虛擬機(jī)(”JVM”),一個Java程序能夠執(zhí)行的軟件環(huán)境。如果你有一個JVM,雖然這個JVM只能用來運(yùn)行Java的程序——但是,JVM能在運(yùn)行在你能想到的每一個平臺之上,這使得Java成為一個具有高移植性的語言。
在Java世界的一個令人著迷的趨勢就是:在最近的幾年里使用JVM來運(yùn)行非Java的程序在程增長的趨勢。畢竟,如果創(chuàng)造了一門新的語言,你就必須在特定的平臺上實(shí)現(xiàn)它。如果你想你的語言能在不同的平臺上移植,那么你就需要為每一個平臺實(shí)現(xiàn)一個版本。但是,相比而言,如果你將語言實(shí)現(xiàn)在JVM上,那么你就能讓你的語言運(yùn)行在任何系統(tǒng)的JVM上,這就意味著幾乎所有平臺都可以運(yùn)行。
于是現(xiàn)在就有了許多的基于JVM的新增語言。其中4個最流行的是發(fā)布在開源許可證之下的?紤]到如今Java也是開發(fā)源碼了,這意味著你可以使用一個全開源體系,并且這個體系是可以移植的。因?yàn)檫@些語言都在JVM之上實(shí)現(xiàn)的,所以你就可以同時訪問Java的標(biāo)準(zhǔn)庫。這意味著如果有一個第三方的的 Java庫,而且你精于Python,那么你就可以使用Jython在你的源代碼中訪問這些Java庫。
早期的基于JVM的腳本語言,就我所知,是Jython,之前被稱為JPython。Jython,從名字你就可以猜到,是一個基于JVM的 Python語言實(shí)現(xiàn)。Jython完全兼容Python2.2的標(biāo)準(zhǔn)版本(這個標(biāo)準(zhǔn)版本的Python也被稱為CPython),這意味著Jython 將會沒有Python的一些新特性。最近發(fā)布的Jython版本是2007年月發(fā)布的,但是Sun雇傭了兩位早期Jython非常知名的開發(fā)者,并且現(xiàn)在 Jython可以運(yùn)行Django應(yīng)用程序框架,因此驗(yàn)證其兼容Python的能力
Sun公司同時資助了JRuby的開發(fā),一個基于JVM的Ruby版本。Jython是Python唯一的兩個實(shí)現(xiàn)的其中之一,對比而言,JRuby則是眾多Ruby語言實(shí)現(xiàn)的其中之一。然而,JRuby被廣泛的認(rèn)為是一個非常重要的版本。特別是因?yàn)樗男,和高度兼容?biāo)準(zhǔn)C的 Ruby版本實(shí)現(xiàn)。JRuby同樣可以運(yùn)行Ruby on Rails框架(譯者注:構(gòu)建在Ruby之上的WEB應(yīng)用框架),此外還能運(yùn)行其他眾多的功能。
Jython和JRuby都是從其他已存在的語言中移植到JVM中來的。而全新的基于JVM的腳本語言是Groovy和Scala。這兩門語言現(xiàn)在都越來越流行,不同的是,Groovy是動態(tài)腳本語言,而是Scala是靜態(tài)語言。使用Groovy最著名的應(yīng)用是Groovy on Grails項目,一個用Groovy寫成,運(yùn)行在JVM之上的WEB應(yīng)用框架(和Ruby on Rails很相似)。Grails找到通向商業(yè)應(yīng)用程序的道路,最著名的就是LinkedIn,使用Linkedin,開發(fā)人員發(fā)現(xiàn)他們能比直接使用 Java更快速和容易的開發(fā)程序。相比而言,Scala,而是強(qiáng)類型是語言,Steve Yegge最近的一次訪談中曾經(jīng)談到、靜態(tài)語言和動態(tài)語言的爭論,因?yàn)檫@個他還受到了很多的批評(譯者注:關(guān)于Steve Yegge的這篇關(guān)于動態(tài)語言和靜態(tài)語言之爭可以查看這里Steve Yegge是一個動態(tài)語言的支持者)
Java已經(jīng)被公認(rèn)為是非常成功而流行的語言。現(xiàn)在,Java也同時也被認(rèn)為是非常流行的平臺,這四類語言僅僅是在不遠(yuǎn)的將來通過JVM來實(shí)現(xiàn)的新興語言的開始。
]]>