既然Java不過另一種類型的程序設(shè)計(jì)語言,大家可能會(huì)奇怪它為什么值得如此重視,為什么還有這么多的人認(rèn)為它是計(jì)算機(jī)程序設(shè)計(jì)的一個(gè)里程碑呢?如果您來自一個(gè)傳統(tǒng)的程序設(shè)計(jì)背景,那么答案在剛開始的時(shí)候并不是很明顯香嗓。Java除了可解決傳統(tǒng)的程序設(shè)計(jì)問題以外,還能解決World Wide Web(萬維網(wǎng))上的編程問題装畅。
1.11.1 什么是Web靠娱?
Web這個(gè)詞剛開始顯得有些泛泛,似乎“沖浪”掠兄、“網(wǎng)上存在”以及“主頁(yè)”等等都和它拉上了一些關(guān)系像云。甚至還有一種“Internet綜合癥”的說法,對(duì)許多人狂熱的上網(wǎng)行為提出了質(zhì)疑蚂夕。我們?cè)谶@里有必要作一些深入的探討迅诬,但在這之前,必須理解客戶機(jī)/服務(wù)器系統(tǒng)的概念婿牍,這是充斥著許多令人迷惑的問題的又一個(gè)計(jì)算領(lǐng)域侈贷。
1. 客戶機(jī)/服務(wù)器計(jì)算
客戶機(jī)/服務(wù)器系統(tǒng)的基本思想是我們能在一個(gè)統(tǒng)一的地方集中存放信息資源。一般將數(shù)據(jù)集中保存在某個(gè)數(shù)據(jù)庫(kù)中等脂,根據(jù)其他人或者機(jī)器的請(qǐng)求將信息投遞給對(duì)方铐维。客戶機(jī)/服務(wù)器概述的一個(gè)關(guān)鍵在于信息是“集中存放”的慎菲。所以我們能方便地更改信息,然后將修改過的信息發(fā)放給信息的消費(fèi)者锨并。將各種元素集中到一起露该,信息倉(cāng)庫(kù)、用于投遞信息的軟件以及信息及軟件所在的那臺(tái)機(jī)器第煮,它們聯(lián)合起來便叫作“服務(wù)器”(Server)解幼。而對(duì)那些駐留在遠(yuǎn)程機(jī)器上的軟件,它們需要與服務(wù)器通信包警,取回信息撵摆,進(jìn)行適當(dāng)?shù)奶幚恚缓笤谶h(yuǎn)程機(jī)器上顯示出來害晦,這些就叫作“客戶”(Client)特铝。
這樣看來暑中,客戶機(jī)/服務(wù)器的基本概念并不復(fù)雜。這里要注意的一個(gè)主要問題是單個(gè)服務(wù)器需要同時(shí)向多個(gè)客戶提供服務(wù)鲫剿。在這一機(jī)制中鳄逾,通常少不了一套數(shù)據(jù)庫(kù)管理系統(tǒng),使設(shè)計(jì)人員能將數(shù)據(jù)布局封裝到表格中灵莲,以獲得最優(yōu)的使用雕凹。除此以外,系統(tǒng)經(jīng)常允許客戶將新信息插入一個(gè)服務(wù)器政冻。這意味著必須確泵兜郑客戶的新數(shù)據(jù)不會(huì)與其他客戶的新數(shù)據(jù)沖突,或者說需要保證那些數(shù)據(jù)在加入數(shù)據(jù)庫(kù)的時(shí)候不會(huì)丟失(用數(shù)據(jù)庫(kù)的術(shù)語來說明场,這叫作“事務(wù)處理”)汽摹。客戶軟件發(fā)生了改變之后榕堰,它們必須在客戶機(jī)器上構(gòu)建竖慧、調(diào)試以及安裝。所有這些會(huì)使問題變得比我們一般想象的復(fù)雜得多逆屡。另外圾旨,對(duì)多種類型的計(jì)算機(jī)和操作系統(tǒng)的支持也是一個(gè)大問題。最后魏蔗,性能的問題顯得尤為重要:可能會(huì)有數(shù)百個(gè)客戶同時(shí)向服務(wù)器發(fā)出請(qǐng)求砍的。所以任何微小的延誤都是不能忽視的。為盡可能緩解潛伏的問題莺治,程序員需要謹(jǐn)慎地分散任務(wù)的處理負(fù)擔(dān)廓鞠。一般可以考慮讓客戶機(jī)負(fù)擔(dān)部分處理任務(wù),但有時(shí)亦可分派給服務(wù)器所在地的其他機(jī)器谣旁,那些機(jī)器亦叫作“中間件”(中間件也用于改進(jìn)對(duì)系統(tǒng)的維護(hù))床佳。
所以在具體實(shí)現(xiàn)的時(shí)候,其他人發(fā)布信息這樣一個(gè)簡(jiǎn)單的概念可能變得異常復(fù)雜榄审。有時(shí)甚至?xí)谷水a(chǎn)生完全無從著手的感覺砌们。客戶機(jī)/服務(wù)器的概念在這時(shí)就可以大顯身手了搁进。事實(shí)上浪感,大約有一半的程序設(shè)計(jì)活動(dòng)都可以采用客戶機(jī)/服務(wù)器的結(jié)構(gòu)。這種系統(tǒng)可負(fù)責(zé)從處理訂單及信用卡交易饼问,一直到發(fā)布各類數(shù)據(jù)的方方面面的任務(wù)——股票市場(chǎng)影兽、科學(xué)研究、政府運(yùn)作等等莱革。在過去峻堰,我們一般為單獨(dú)的問題采取單獨(dú)的解決方案讹开;每次都要設(shè)計(jì)一套新方案。這些方案無論創(chuàng)建還是使用都比較困難茧妒,用戶每次都要學(xué)習(xí)和適應(yīng)新界面萧吠。客戶機(jī)/服務(wù)器問題需要從根本上加以變革桐筏!
2. Web是一個(gè)巨大的服務(wù)器
Web實(shí)際就是一套規(guī)模巨大的客戶機(jī)/服務(wù)器系統(tǒng)纸型。但它的情況要復(fù)雜一些,因?yàn)樗蟹?wù)器和客戶都同時(shí)存在于單個(gè)網(wǎng)絡(luò)上面梅忌。但我們沒必要了解更進(jìn)一步的細(xì)節(jié)狰腌,因?yàn)槲ㄒ灰P(guān)心的就是一次建立同一個(gè)服務(wù)器的連接,并同它打交道(即使可能要在全世界的范圍內(nèi)搜索正確的服務(wù)器)牧氮。
最開始的時(shí)候琼腔,這是一個(gè)簡(jiǎn)單的單向操作過程。我們向一個(gè)服務(wù)器發(fā)出請(qǐng)求踱葛,它向我們回傳一個(gè)文件丹莲,由于本機(jī)的瀏覽器軟件(亦即“客戶”或“客戶程序”)負(fù)責(zé)解釋和格式化,并在我們面前的屏幕上正確地顯示出來尸诽。但人們不久就不滿足于只從一個(gè)服務(wù)器傳遞網(wǎng)頁(yè)甥材。他們希望獲得完全的客戶機(jī)/服務(wù)器能力,使客戶(程序)也能反饋一些信息到服務(wù)器性含。比如希望對(duì)服務(wù)器上的數(shù)據(jù)庫(kù)進(jìn)行檢索洲赵,向服務(wù)器添加新信息,或者下一份訂單等等(這也提供了比以前的系統(tǒng)更高的安全要求)商蕴。在Web的發(fā)展過程中叠萍,我們可以很清晰地看出這些令人心喜的變化。
Web瀏覽器的發(fā)展終于邁出了重要的一步:某個(gè)信息可在任何類型的計(jì)算機(jī)上顯示出來绪商,毋需任何改動(dòng)苛谷。然而,瀏覽器仍然顯得很原始格郁,在用戶迅速增多的要求面前顯得有些力不從心抄腔。它們的交互能力不夠強(qiáng),而且對(duì)服務(wù)器和因特網(wǎng)都造成了一定程度的干擾理张。這是由于每次采取一些要求編程的操作時(shí),必須將信息反饋回服務(wù)器绵患,在服務(wù)器那一端進(jìn)行處理雾叭。所以完全可能需要等待數(shù)秒乃至數(shù)分鐘的時(shí)間才會(huì)發(fā)現(xiàn)自己剛才拼錯(cuò)了一個(gè)單詞。由于瀏覽器只是一個(gè)純粹的查看程序落蝙,所以連最簡(jiǎn)單的計(jì)算任務(wù)都不能進(jìn)行(當(dāng)然在另一方面织狐,它也顯得非常安全暂幼,因?yàn)椴荒茉诒緳C(jī)上面執(zhí)行任何程序,避開了程序錯(cuò)誤或者病毒的騷擾)移迫。
為解決這個(gè)問題旺嬉,人們采取了許多不同的方法。最開始的時(shí)候厨埋,人們對(duì)圖形標(biāo)準(zhǔn)進(jìn)行了改進(jìn)邪媳,使瀏覽器能顯示更好的動(dòng)畫和視頻。為解決剩下的問題荡陷,唯一的辦法就是在客戶端(瀏覽器)內(nèi)運(yùn)行程序雨效。這就叫作“客戶端編程”,它是對(duì)傳統(tǒng)的“服務(wù)器端編程”的一個(gè)非常重要的拓展废赞。
1.11.2 客戶端編程(注釋⑧)
Web最初采用的“服務(wù)器-瀏覽器”方案可提供交互式內(nèi)容徽龟,但這種交互能力完全由服務(wù)器提供,為服務(wù)器和因特網(wǎng)帶來了不小的負(fù)擔(dān)唉地。服務(wù)器一般為客戶瀏覽器產(chǎn)生靜態(tài)網(wǎng)頁(yè)据悔,由后者簡(jiǎn)單地解釋并顯示出來≡耪樱基本HTML語言提供了簡(jiǎn)單的數(shù)據(jù)收集機(jī)制:文字輸入框极颓、復(fù)選框、單選鈕耕拷、列表以及下拉列表等讼昆,另外還有一個(gè)按鈕,只能由程序規(guī)定重新設(shè)置表單中的數(shù)據(jù)骚烧,以便回傳給服務(wù)器浸赫。用戶提交的信息通過所有Web服務(wù)器均能支持的“通用網(wǎng)關(guān)接口”(CGI)回傳到服務(wù)器。包含在提交數(shù)據(jù)中的文字指示CGI該如何操作赃绊。最常見的行動(dòng)是運(yùn)行位于服務(wù)器的一個(gè)程序既峡。那個(gè)程序一般保存在一個(gè)名為“cgi-bin”的目錄中(按下Web頁(yè)內(nèi)的一個(gè)按鈕時(shí),請(qǐng)注意一下瀏覽器頂部的地址窗碧查,經(jīng)常都能發(fā)現(xiàn)“cgi-bin”的字樣)运敢。大多數(shù)語言都可用來編制這些程序,但其中最常見的是Perl忠售。這是由于Perl是專為文字的處理及解釋而設(shè)計(jì)的传惠,所以能在任何服務(wù)器上安裝和使用,無論采用的處理器或操作系統(tǒng)是什么稻扬。
⑧:本節(jié)內(nèi)容改編自某位作者的一篇文章卦方。那篇文章最早出現(xiàn)在位于www.mainspring.com的Mainspring上。本節(jié)的采用已征得了對(duì)方的同意泰佳。
今天的許多Web站點(diǎn)都嚴(yán)格地建立在CGI的基礎(chǔ)上盼砍,事實(shí)上幾乎所有事情都可用CGI做到尘吗。唯一的問題就是響應(yīng)時(shí)間。CGI程序的響應(yīng)取決于需要傳送多少數(shù)據(jù)浇坐,以及服務(wù)器和因特網(wǎng)兩方面的負(fù)擔(dān)有多重(而且CGI程序的啟動(dòng)比較慢)睬捶。Web的早期設(shè)計(jì)者并未預(yù)料到當(dāng)初綽綽有余的帶寬很快就變得不夠用,這正是大量應(yīng)用充斥網(wǎng)上造成的結(jié)果近刘。例如擒贸,此時(shí)任何形式的動(dòng)態(tài)圖形顯示都幾乎不能連貫地顯示,因?yàn)榇藭r(shí)必須創(chuàng)建一個(gè)GIF文件跌宛,再將圖形的每種變化從服務(wù)器傳遞給客戶酗宋。而且大家應(yīng)該對(duì)輸入表單上的數(shù)據(jù)校驗(yàn)有著深刻的體會(huì)。原來的方法是我們按下網(wǎng)頁(yè)上的提交按鈕(Submit)疆拘;數(shù)據(jù)回傳給服務(wù)器蜕猫;服務(wù)器啟動(dòng)一個(gè)CGI程序,檢查用戶輸入是否有錯(cuò)哎迄;格式化一個(gè)HTML頁(yè)回右,通知可能遇到的錯(cuò)誤,并將這個(gè)頁(yè)回傳給我們漱挚;隨后必須回到原先那個(gè)表單頁(yè)翔烁,再輸入一遍。這種方法不僅速度非常慢旨涝,也顯得非常繁瑣蹬屹。
解決的辦法就是客戶端的程序設(shè)計(jì)。運(yùn)行Web瀏覽器的大多數(shù)機(jī)器都擁有足夠強(qiáng)的能力白华,可進(jìn)行其他大量工作慨默。與此同時(shí),原始的靜態(tài)HTML方法仍然可以采用弧腥,它會(huì)一直等到服務(wù)器送回下一個(gè)頁(yè)厦取。客戶端編程意味著Web瀏覽器可獲得更充分的利用管搪,并可有效改善Web服務(wù)器的交互(互動(dòng))能力虾攻。
對(duì)客戶端編程的討論與常規(guī)編程問題的討論并沒有太大的區(qū)別。采用的參數(shù)肯定是相同的更鲁,只是運(yùn)行的平臺(tái)不同:Web瀏覽器就象一個(gè)有限的操作系統(tǒng)霎箍。無論如何,我們?nèi)匀恍枰幊淘栉匀粫?huì)在客戶端編程中遇到大量問題漂坏,同時(shí)也有很多解決的方案。在本節(jié)剩下的部分里,我們將對(duì)這些問題進(jìn)行一番概括樊拓,并介紹在客戶端編程中采取的對(duì)策。
1. 插件
朝客戶端編程邁進(jìn)的時(shí)候塘慕,最重要的一個(gè)問題就是插件的設(shè)計(jì)筋夏。利用插件,程序員可以方便地為瀏覽器添加新功能图呢,用戶只需下載一些代碼条篷,把它們“插入”瀏覽器的適當(dāng)位置即可。這些代碼的作用是告訴瀏覽器“從現(xiàn)在開始蛤织,你可以進(jìn)行這些新活動(dòng)了”(僅需下載這些插入一次)赴叹。有些快速和功能強(qiáng)大的行為是通過插件添加到瀏覽器的。但插件的編寫并不是一件簡(jiǎn)單的任務(wù)指蚜。在我們構(gòu)建一個(gè)特定的站點(diǎn)時(shí)乞巧,可能并不希望涉及這方面的工作。對(duì)客戶端程序設(shè)計(jì)來說摊鸡,插件的價(jià)值在于它允許專業(yè)程序員設(shè)計(jì)出一種新的語言绽媒,并將那種語言添加到瀏覽器,同時(shí)不必經(jīng)過瀏覽器原創(chuàng)者的許可免猾。由此可以看出是辕,插件實(shí)際是瀏覽器的一個(gè)“后門”,允許創(chuàng)建新的客戶端程序設(shè)計(jì)語言(盡管并非所有語言都是作為插件實(shí)現(xiàn)的)猎提。
2. 腳本編制語言
插件造成了腳本編制語言的爆炸性增長(zhǎng)获三。通過這種腳本語言,可將用于自己客戶端程序的源碼直接插入HTML頁(yè)锨苏,而對(duì)那種語言進(jìn)行解釋的插件會(huì)在HTML頁(yè)顯示的時(shí)候自動(dòng)激活疙教。腳本語言一般都傾向于盡量簡(jiǎn)化,易于理解蚓炬。而且由于它們是從屬于HTML頁(yè)的一些簡(jiǎn)單正文松逊,所以只需向服務(wù)器發(fā)出對(duì)那個(gè)頁(yè)的一次請(qǐng)求,即可非晨舷模快地載入经宏。缺點(diǎn)是我們的代碼全部暴露在人們面前。另一方面驯击,由于通常不用腳本編制語言做過份復(fù)雜的事情烁兰,所以這個(gè)問題暫且可以放在一邊。
腳本語言真正面向的是特定類型問題的解決徊都,其中主要涉及如何創(chuàng)建更豐富沪斟、更具有互動(dòng)能力的圖形用戶界面(GUI)。然而,腳本語言也許能解決客戶端編程中80%的問題主之。你碰到的問題可能完全就在那80%里面择吊。而且由于腳本編制語言的宗旨是盡可能地簡(jiǎn)化與快速,所以在考慮其他更復(fù)雜的方案之前(如Java及ActiveX)槽奕,首先應(yīng)想一下腳本語言是否可行几睛。
目前討論得最多的腳本編制語言包括JavaScript(它與Java沒有任何關(guān)系;之所以叫那個(gè)名字粤攒,完全是一種市場(chǎng)策略)所森、VBScript(同Visual Basic很相似)以及Tcl/Tk(來源于流行的跨平臺(tái)GUI構(gòu)造語言)。當(dāng)然還有其他許多語言夯接,也有許多正在開發(fā)中焕济。
JavaScript也許是目常用的,它得到的支持也最全面盔几。無論NetscapeNavigator晴弃,Microsoft Internet Explorer,還是Opera问欠,目前都提供了對(duì)JavaScript的支持肝匆。除此以外,市面上講述JavaScript的書籍也要比講述其他語言的書多得多顺献。有些工具還能利用JavaScript自動(dòng)產(chǎn)生網(wǎng)頁(yè)旗国。當(dāng)然,如果你已經(jīng)有Visual Basic或者Tcl/Tk的深厚功底,當(dāng)然用它們要簡(jiǎn)單得多,起碼可以避免學(xué)習(xí)新語言的煩惱(解決Web方面的問題就已經(jīng)夠讓人頭痛了)轩猩。
3. Java
如果說一種腳本編制語言能解決80%的客戶端程序設(shè)計(jì)問題,那么剩下的20%又該怎么辦呢寿冕?它們屬于一些高難度的問題嗎?目前最流行的方案就是Java椒袍。它不僅是一種功能強(qiáng)大驼唱、高度安全、可以跨平臺(tái)使用以及國(guó)際通用的程序設(shè)計(jì)語言驹暑,也是一種具有旺盛生命力的語言玫恳。對(duì)Java的擴(kuò)展是不斷進(jìn)行的,提供的語言特性和庫(kù)能夠很好地解決傳統(tǒng)語言不能解決的問題优俘,比如多線程操作京办、數(shù)據(jù)庫(kù)訪問、連網(wǎng)程序設(shè)計(jì)以及分布式計(jì)算等等帆焕。Java通過“程序片”(Applet)巧妙地解決了客戶端編程的問題惭婿。
程序片(或“小應(yīng)用程序”)是一種非常小的程序,只能在Web瀏覽器中運(yùn)行。作為Web頁(yè)的一部分财饥,程序片代碼會(huì)自動(dòng)下載回來(這和網(wǎng)頁(yè)中的圖片差不多)换吧。激活程序片后,它會(huì)執(zhí)行一個(gè)程序钥星。程序片的一個(gè)優(yōu)點(diǎn)體現(xiàn)在:通過程序片式散,一旦用戶需要客戶軟件,軟件就可從服務(wù)器自動(dòng)下載回來打颤。它們能自動(dòng)取得客戶軟件的最新版本,不會(huì)出錯(cuò)漓滔,也沒有重新安裝的麻煩编饺。由于Java的設(shè)計(jì)原理,程序員只需要?jiǎng)?chuàng)建程序的一個(gè)版本响驴,那個(gè)程序能在幾乎所有計(jì)算機(jī)以及安裝了Java解釋器的瀏覽器中運(yùn)行透且。由于Java是一種全功能的編程語言,所以在向服務(wù)器發(fā)出一個(gè)請(qǐng)求之前豁鲤,我們能先在客戶端做完盡可能多的工作秽誊。例如,再也不必通過因特網(wǎng)傳送一個(gè)請(qǐng)求表單琳骡,再由服務(wù)器確定其中是否存在一個(gè)拼寫或者其他參數(shù)錯(cuò)誤锅论。大多數(shù)數(shù)據(jù)校驗(yàn)工作均可在客戶端完成,沒有必要坐在計(jì)算機(jī)前面焦急地等待服務(wù)器的響應(yīng)楣号。這樣一來最易,不僅速度和響應(yīng)的靈敏度得到了極大的提高,對(duì)網(wǎng)絡(luò)和服務(wù)器造成的負(fù)擔(dān)也可以明顯減輕炫狱,這對(duì)保障因特網(wǎng)的暢通是至關(guān)重要的藻懒。
與腳本程序相比,Java程序片的另一個(gè)優(yōu)點(diǎn)是它采用編譯好的形式视译,所以客戶端看不到源碼嬉荆。當(dāng)然在另一方面,反編譯Java程序片也并不是件難事酷含,而且代碼的隱藏一般并不是個(gè)重要的問題鄙早。大家要注意另外兩個(gè)重要的問題。正如本書以前會(huì)講到的那樣第美,編譯好的Java程序片可能包含了許多模塊蝶锋,所以要多次“命中”(訪問)服務(wù)器以便下載(在Java 1.1中,這個(gè)問題得到了有效的改善——利用Java壓縮檔什往,即JAR文件——它允許設(shè)計(jì)者將所有必要的模塊都封裝到一起扳缕,供用戶統(tǒng)一下載)。在另一方面,腳本程序是作為Web頁(yè)正文的一部分集成到Web頁(yè)內(nèi)的躯舔。這種程序一般都非常小驴剔,可有效減少對(duì)服務(wù)器的點(diǎn)擊數(shù)。另一個(gè)因素是學(xué)習(xí)方面的問題粥庄。不管你平時(shí)聽別人怎么說丧失,Java都不是一種十分容易便可學(xué)會(huì)的語言。如果你以前是一名Visual Basic程序員惜互,那么轉(zhuǎn)向VBScript會(huì)是一種最快捷的方案布讹。由于VBScript可以解決大多數(shù)典型的客戶機(jī)/服務(wù)器問題,所以一旦上手训堆,就很難下定決心再去學(xué)習(xí)Java描验。如果對(duì)腳本編制語言比較熟,那么在轉(zhuǎn)向Java之前坑鱼,建議先熟悉一下JavaScript或者VBScript膘流,因?yàn)樗鼈兛赡芤呀?jīng)能夠滿足你的需要,不必經(jīng)歷學(xué)習(xí)Java的艱苦過程鲁沥。
4. ActiveX
在某種程度上呼股,Java的一個(gè)有力競(jìng)爭(zhēng)對(duì)手應(yīng)該是微軟的ActiveX,盡管它采用的是完全不同的一套實(shí)現(xiàn)機(jī)制画恰。ActiveX最早是一種純Windows的方案彭谁。經(jīng)過一家獨(dú)立的專業(yè)協(xié)會(huì)的努力,ActiveX現(xiàn)在已具備了跨平臺(tái)使用的能力允扇。實(shí)際上马靠,ActiveX的意思是“假如你的程序同它的工作環(huán)境正常連接,它就能進(jìn)入Web頁(yè)蔼两,并在支持ActiveX的瀏覽器中運(yùn)行”(IE固化了對(duì)ActiveX的支持甩鳄,而Netscape需要一個(gè)插件)。所以额划,ActiveX并沒有限制我們使用一種特定的語言妙啃。比如,假設(shè)我們已經(jīng)是一名有經(jīng)驗(yàn)的Windows程序員俊戳,能熟練地使用象C++揖赴、Visual Basic或者BorlandDelphi那樣的語言,就能幾乎不加任何學(xué)習(xí)地創(chuàng)建出ActiveX組件抑胎。事實(shí)上燥滑,ActiveX是在我們的Web頁(yè)中使用“歷史遺留”代碼的最佳途徑。
5. 安全
自動(dòng)下載和通過因特網(wǎng)運(yùn)行程序聽起來就象是一個(gè)病毒制造者的夢(mèng)想阿逃。在客戶端的編程中铭拧,ActiveX帶來了最讓人頭痛的安全問題赃蛛。點(diǎn)擊一個(gè)Web站點(diǎn)的時(shí)候,可能會(huì)隨同HTML網(wǎng)頁(yè)傳回任何數(shù)量的東西:GIF文件搀菩、腳本代碼呕臂、編譯好的Java代碼以及ActiveX組件。有些是無害的肪跋;GIF文件不會(huì)對(duì)我們?cè)斐扇魏挝:ζ缃_本編制語言通常在自己可做的事情上有著很大的限制。Java也設(shè)計(jì)成在一個(gè)安全“沙箱”里在它的程序片中運(yùn)行州既,這樣可防止操作位于沙箱以外的磁盤或者內(nèi)存區(qū)域谜洽。
ActiveX是所有這些里面最讓人擔(dān)心的。用ActiveX編寫程序就象編制Windows應(yīng)用程序——可以做自己想做的任何事情吴叶。下載回一個(gè)ActiveX組件后褥琐,它完全可能對(duì)我們磁盤上的文件造成破壞。當(dāng)然晤郑,對(duì)那些下載回來并不限于在Web瀏覽器內(nèi)部運(yùn)行的程序,它們同樣也可能破壞我們的系統(tǒng)贸宏。從BBS下載回來的病毒一直是個(gè)大問題造寝,但因特網(wǎng)的速度使得這個(gè)問題變得更加復(fù)雜。
目前解決的辦法是“數(shù)字簽名”吭练,代碼會(huì)得到權(quán)威機(jī)構(gòu)的驗(yàn)證诫龙,顯示出它的作者是誰。這一機(jī)制的基礎(chǔ)是認(rèn)為病毒之所以會(huì)傳播鲫咽,是由于它的編制者匿名的緣故签赃。所以假如去掉了匿名的因素,所有設(shè)計(jì)者都不得不為它們的行為負(fù)責(zé)分尸。這似乎是一個(gè)很好的主意锦聊,因?yàn)樗钩绦蝻@得更加正規(guī)。但我對(duì)它能消除惡意因素持懷疑態(tài)度箩绍,因?yàn)榧偃缫粋€(gè)程序便含有Bug孔庭,那么同樣會(huì)造成問題。
Java通過“沙箱”來防止這些問題的發(fā)生材蛛。Java解釋器內(nèi)嵌于我們本地的Web瀏覽器中圆到,在程序片裝載時(shí)會(huì)檢查所有有嫌疑的指令。特別地卑吭,程序片根本沒有權(quán)力將文件寫進(jìn)磁盤芽淡,或者刪除文件(這是病毒最喜歡做的事情之一)。我們通常認(rèn)為程序片是安全的豆赏。而且由于安全對(duì)于營(yíng)建一套可靠的客戶機(jī)/服務(wù)器系統(tǒng)至關(guān)重要挣菲,所以會(huì)給病毒留下漏洞的所有錯(cuò)誤都能很快得到修復(fù)(瀏覽器軟件實(shí)際需要強(qiáng)行遵守這些安全規(guī)則富稻;而有些瀏覽器則允許我們選擇不同的安全級(jí)別,防止對(duì)系統(tǒng)不同程度的訪問)己单。
大家或許會(huì)懷疑這種限制是否會(huì)妨礙我們將文件寫到本地磁盤唉窃。比如,我們有時(shí)需要構(gòu)建一個(gè)本地?cái)?shù)據(jù)庫(kù)纹笼,或?qū)?shù)據(jù)保存下來纹份,以便日后離線使用。最早的版本似乎每個(gè)人都能在線做任何敏感的事情廷痘,但這很快就變得非常不現(xiàn)實(shí)(盡管低價(jià)“互聯(lián)網(wǎng)工具”有一天可能會(huì)滿足大多數(shù)用戶的需要)蔓涧。解決的方案是“簽了名的程序片”,它用公共密鑰加密算法驗(yàn)證程序片確實(shí)來自它所聲稱的地方笋额。當(dāng)然在通過驗(yàn)證后元暴,簽了名的一個(gè)程序片仍然可以開始清除你的磁盤。但從理論上說兄猩,既然現(xiàn)在能夠找到創(chuàng)建人“算帳”茉盏,他們一般不會(huì)干這種蠢事。Java 1.1為數(shù)字簽名提供了一個(gè)框架枢冤,在必要時(shí)鸠姨,可讓一個(gè)程序片“走”到沙箱的外面來。
數(shù)字簽名遺漏了一個(gè)重要的問題淹真,那就是人們?cè)谝蛱鼐W(wǎng)上移動(dòng)的速度讶迁。如下載回一個(gè)錯(cuò)誤百出的程序,而它很不幸地真的干了某些蠢事核蘸,需要多久的時(shí)間才能發(fā)覺這一點(diǎn)呢巍糯?這也許是幾天,也可能幾周之后客扎。發(fā)現(xiàn)了之后祟峦,又如何追蹤當(dāng)初肇事的程序呢(以及它當(dāng)時(shí)的責(zé)任有多大)?
6. 因特網(wǎng)和內(nèi)聯(lián)網(wǎng)
Web是解決客戶機(jī)/服務(wù)器問題的一種常用方案徙鱼,所以最好能用相同的技術(shù)解決此類問題的一些“子集”搀愧,特別是公司內(nèi)部的傳統(tǒng)客戶機(jī)/服務(wù)器問題。對(duì)于傳統(tǒng)的客戶機(jī)/服務(wù)器模式疆偿,我們面臨的問題是擁有多種不同類型的客戶計(jì)算機(jī)咱筛,而且很難安裝新的客戶軟件。但通過Web瀏覽器和客戶端編程杆故,這兩類問題都可得到很好的解決迅箩。若一個(gè)信息網(wǎng)絡(luò)局限于一家特定的公司,那么在將Web技術(shù)應(yīng)用于它之后处铛,即可稱其為“內(nèi)聯(lián)網(wǎng)”(Intranet)饲趋,以示與國(guó)際性的“因特網(wǎng)”(Internet)有別拐揭。內(nèi)聯(lián)網(wǎng)提供了比因特網(wǎng)更大的安全級(jí)別,因?yàn)榭梢晕锢硇缘乜刂茖?duì)公司內(nèi)部服務(wù)器的使用奕塑。說到培訓(xùn)堂污,一般只要人們理解了瀏覽器的常規(guī)概念,就可以非常輕松地掌握網(wǎng)頁(yè)和程序片之間的差異龄砰,所以學(xué)習(xí)新型系統(tǒng)的開銷會(huì)大幅度減少盟猖。
安全問題將我們引入客戶端編程領(lǐng)域一個(gè)似乎是自動(dòng)形成的分支。若程序是在因特網(wǎng)上運(yùn)行换棚,由于無從知曉它會(huì)在什么平臺(tái)上運(yùn)行式镐,所以編程時(shí)要特別留意,防范可能出現(xiàn)的編程錯(cuò)誤固蚤。需作一些跨平臺(tái)處理娘汞,以及適當(dāng)?shù)陌踩婪叮热绮捎媚撤N腳本語言或者Java夕玩。
但假如在內(nèi)聯(lián)網(wǎng)中運(yùn)行你弦,面臨的一些制約因素就會(huì)發(fā)生變化。全部機(jī)器均為Intel/Windows平臺(tái)是件很平常的事情燎孟。在內(nèi)聯(lián)網(wǎng)中禽作,需要對(duì)自己代碼的質(zhì)量負(fù)責(zé)。而且一旦發(fā)現(xiàn)錯(cuò)誤缤弦,就可以馬上改正。除此以外彻磁,可能已經(jīng)有了一些“歷史遺留”的代碼碍沐,并用較傳統(tǒng)的客戶機(jī)/服務(wù)器方式使用那些代碼。但在進(jìn)行升級(jí)時(shí)衷蜓,每次都要物理性地安裝一道客戶程序累提。浪費(fèi)在升級(jí)安裝上的時(shí)間是轉(zhuǎn)移到瀏覽器的一項(xiàng)重要原因。使用了瀏覽器后磁浇,升級(jí)就變得易如反掌斋陪,而且整個(gè)過程是透明和自動(dòng)進(jìn)行的。如果真的是牽涉到這樣的一個(gè)內(nèi)聯(lián)網(wǎng)中置吓,最明智的方法是采用ActiveX无虚,而非試圖采用一種新的語言來改寫程序代碼。
面臨客戶端編程問題令人困惑的一系列解決方案時(shí)衍锚,最好的方案是先做一次投資/回報(bào)分析友题。請(qǐng)總結(jié)出問題的全部制約因素,以及什么才是最快的方案戴质。由于客戶端程序設(shè)計(jì)仍然要編程度宦,所以無論如何都該針對(duì)自己的特定情況采取最好的開發(fā)途徑踢匣。這是準(zhǔn)備面對(duì)程序開發(fā)中一些不可避免的問題時(shí),我們可以作出的最佳姿態(tài)戈抄。
1.11.3 服務(wù)器端編程
我們的整個(gè)討論都忽略了服務(wù)器端編程的問題离唬。如果向服務(wù)器發(fā)出一個(gè)請(qǐng)求,會(huì)發(fā)生什么事情划鸽?大多數(shù)時(shí)候的請(qǐng)求都是很簡(jiǎn)單的一個(gè)“把這個(gè)文件發(fā)給我”输莺。瀏覽器隨后會(huì)按適當(dāng)?shù)男问浇忉屵@個(gè)文件:作為HTML頁(yè)、一幅圖漾稀、一個(gè)Java程序片模闲、一個(gè)腳本程序等等。向服務(wù)器發(fā)出的較復(fù)雜的請(qǐng)求通常涉及到對(duì)一個(gè)數(shù)據(jù)庫(kù)進(jìn)行操作(事務(wù)處理)崭捍。其中最常見的就是發(fā)出一個(gè)數(shù)據(jù)庫(kù)檢索命令尸折,得到結(jié)果后,服務(wù)器會(huì)把它格式化成HTML頁(yè)殷蛇,并作為結(jié)果傳回來(當(dāng)然实夹,假如客戶通過Java或者某種腳本語言具有了更高的智能,那么原始數(shù)據(jù)就能在客戶端發(fā)送和格式化粒梦;這樣做速度可以更快亮航,也能減輕服務(wù)器的負(fù)擔(dān))。另外匀们,有時(shí)需要在數(shù)據(jù)庫(kù)中注冊(cè)自己的名字(比如加入一個(gè)組時(shí))缴淋,或者向服務(wù)器發(fā)出一份訂單,這就涉及到對(duì)那個(gè)數(shù)據(jù)庫(kù)的修改泄朴。這類服務(wù)器請(qǐng)求必須通過服務(wù)器端的一些代碼進(jìn)行重抖,我們稱其為“服務(wù)器端的編程”。在傳統(tǒng)意義上祖灰,服務(wù)器端編程是用Perl和CGI腳本進(jìn)行的钟沛,但更復(fù)雜的系統(tǒng)已經(jīng)出現(xiàn)。其中包括基于Java的Web服務(wù)器局扶,它允許我們用Java進(jìn)行所有服務(wù)器端編程恨统,寫出的程序就叫作“小服務(wù)程序”(Servlet)。
1.11.4 一個(gè)獨(dú)立的領(lǐng)域:應(yīng)用程序
與Java有關(guān)的大多數(shù)爭(zhēng)論都是與程序片有關(guān)的三妈。Java實(shí)際是一種常規(guī)用途的程序設(shè)計(jì)語言畜埋,可解決任何類型的問題,至少理論上如此畴蒲。而且正如前面指出的由捎,可以用更有效的方式來解決大多數(shù)客戶機(jī)/服務(wù)器問題。如果將視線從程序片身上轉(zhuǎn)開(同時(shí)放寬一些限制饿凛,比如禁止寫盤等)狞玛,就進(jìn)入了常規(guī)用途的應(yīng)用程序的廣闊領(lǐng)域软驰。這種應(yīng)用程序可獨(dú)立運(yùn)行,毋需瀏覽器心肪,就象普通的執(zhí)行程序那樣锭亏。在這兒,Java的特色并不僅僅反應(yīng)在它的移植能力硬鞍,也反映在編程本身上慧瘤。就象貫穿全書都會(huì)講到的那樣,Java提供了許多有用的特性固该,使我們能在較短的時(shí)間里創(chuàng)建出比用從前的程序設(shè)計(jì)語言更健壯的程序锅减。
但要注意任何東西都不是十全十美的,我們?yōu)榇艘惨冻鲆恍┐鷥r(jià)伐坏。其中最明顯的是執(zhí)行速度放慢了(盡管可對(duì)此進(jìn)行多方面的調(diào)整)怔匣。和任何語言一樣,Java本身也存在一些限制桦沉,使得它不十分適合解決某些特殊的編程問題每瞒。但不管怎樣,Java都是一種正在快速發(fā)展的語言纯露。隨著每個(gè)新版本的發(fā)布剿骨,它變得越來越可愛,能充分解決的問題也變得越來越多埠褪。