<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    iNeo

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      30 Posts :: 8 Stories :: 2 Comments :: 0 Trackbacks

    #


      摘 要:簡要介紹了一種通用的,動態樹型結構的實現方案,該方案基于Asynchronous JavaScript and XML,結合Struts框架設計實現了結構清晰、擴展性良好的多層架構,數據存儲于數據庫,結合XML描述樹的節點信息,使得任何按預定的XML文檔描述的信息都可以通過動態樹來展現。

      關鍵詞:MVC模式;Ajax;樹型結構;字典序

      樹型結構是一類應用非常廣泛的數據結構。人類社會中宗族的族譜和現代企業的組織形式都是樹型結構。在計算機領域中,文件系統中文件的管理結構、存儲器管理中的頁表、數據庫中的索引等也都是樹型結構。隨著Internet的飛速發展,樹型結構在瀏覽器/服務器(Browser/Server,簡稱B/S)應用系統的應用也越來越廣泛。

      目前,在互聯網上廣泛存在、應用的樹型結構一般分為兩種:靜態和動態結構。靜態結構存在最多、實現簡單,但是靜態導致不能改變樹的結構和內容,無法反映樹的節點信息的變化;而實現相對復雜的動態構造樹,雖然可以動態增加、刪除、更新節點信息,但是大部分不能直接拖放節點來改變樹的結構以及節點間的次序,并且反復刷新整個頁面,給用戶維護帶來了許多不便。本文提出了一種基于Ajax (Asynchronous JavaScript and XML)通用的、動態加載節點的解決方案。實現上采用J2EE多層架構,樹節點的描述信息采用數據庫存儲,以可擴展標記語言(eXtensible Markup Language,簡稱XML)展現給JavaScript解析,支持無刷新地增加、刪除、更新節點信息,以及拖放節點來改變樹的結構和節點間的次序。文中第1部分簡要介紹了Ajax技術;第2部分詳細介紹了該方案的技術實現過程;第3部分分析了該方案的效率。

      1、Ajax簡介

      Ajax概念的最早提出者Jesse James Garrett認為:Ajax并不是一門新的語言或技術,它實際上是幾項技術按一定的方式組合在共同的協作中發揮各自的作用,它包括:

      ·使用擴展超媒體標記語言(eXtended Hypertext Markup Language,簡稱XHTML)和級聯樣式單(Cascading Style Sheet,簡稱CSS)標準化呈現;

      ·使用文檔對象模型(Document Object Model,簡稱DOM)實現動態顯示和交互;

      ·使用可擴展標記語言(eXtensible Markup Language,簡稱XML)和可擴展樣式表轉換(eXtensible Stylesheet Language Transformation,簡稱XSLT)進行數據交換與處理;

      ·使用XMLHTTP組件XMLHttpRequest對象進行異步數據讀取;

      ·最后用JavaScript綁定和處理所有數據。

      Ajax的工作原理如圖1所示,它相當于在用戶和服務器之間加了一個中間層,使用戶操作與服務器響應異步化。并不是所有的用戶請求都提交給服務器,像— 些數據驗證和數據處理等都交給Ajax引擎處理,只有確定需要從服務器讀取新數據時再由Ajax引擎代為向服務器提交請求。這樣就把一些服務器負擔的工作轉嫁到客戶端,利用客戶端閑置的處理能力來處理,減輕服務器和帶寬的負擔,從而達到節約ISP的空間及帶寬租用成本的目的。


    圖 1 未使用Ajax(a)和使用Ajax(b)的web應用比較

      2、總體設計方案

      傳統的服務器程序采用Model 1開發模型,通常將業務邏輯、服務器端處理過程和HTML代碼集中在一起表示,快速完成應用開發。Model 1 在小規模應用開發時優勢明顯,但是應用實現一般是基于過程的,一組服務器頁面實現一個流程,如果流程改動將導致多個地方修改,非常不利于應用的擴展和更新。此外業務邏輯和表示邏輯混合在服務器頁面中,耦合緊密,無法模塊化,導致代碼無法復用。

      Model 2則解決了這些問題,它是面向對象的MVC模式(Model-View-Controller,模型-視圖-控制器)在Web開發中的應用,Model表示應用的業務邏輯,View是應用的表示層頁面,Controller是提供應用的處理過程控制。通過這種MVC設計模式把應用邏輯,處理過程和顯示邏輯劃分成不同的組件、模塊實現,組件間可以進行交互和重用。

      本方案是采用J2EE的多層架構,設計時結合Struts框架將表示層、業務邏輯層和數據層劃分成不同的模塊。表示層專注于樹的外觀顯示,業務邏輯層為服務器端處理程序,處理樹的生成、變化,為減少耦合性,該程序全部模塊化實現,不在表示頁面嵌入服務器程序;模型層是數據的存儲和表示。下面分別介紹各層實現。

    原文鏈接:http://www.7dspace.com/doc/44/0512/2005122906292220003.htm
    posted @ 2005-12-30 08:28 只牽這只狗 閱讀(305) | 評論 (0)編輯 收藏

    Google工程師詳述Google的搜索結果排列算法
     

    本文作者馬特-卡茲(Matt Cutts)是Google公司品質管理部門的軟件工程師。他的工作主要是給好的網站評定等級,并負責開發阻止虛假或垃圾網站出現在Google搜索結果上的技術。

    圖書館管理員們提出最多的問題之一是:“對于什么樣的結果應該位于搜索列表的最上方,Google是如何選擇的?”現在品質工程師馬特-卡茲介紹了快速入門的知識,解釋了Google是如何在網上爬行和索引,以及如何評定搜索結果等級的。馬特也向學校圖書館管理員提出建議,告訴他們如何輔導學生。

    爬行和索引

    在你瀏覽包含了Google搜索結果的網頁之前,要發生很多事情。首先是在萬維網數以十億計的網頁上爬行和索引,這個工作是由Googlebot完成的,它負責與全球的網絡服務器連接以收集文件。爬行不是真的在網上漫游,而是訪問網絡服務器返回到一個特定的網頁上,接著掃描該網頁建立超鏈接并為每一個網頁編上號碼。爬行可收集大量的文件,但這些文件還不能直接用于搜索。

    如果沒有索引,在你想查詢如“civil war”(南北戰爭)等內容時,Google的服務器將不得不在你每次搜索時閱讀每一份文件的內容。因此第二個步驟是要建立一個索引,這樣就需要“轉換” 爬行所獲得的數據。為了不必在每一份文件上掃描每一個單詞,就需要在數據上做些文章,以便顯示包含了特定單詞的所有文件。例如,假設單詞“civil”在編號為3、8、22、56、68和92的文件上出現過,而單詞“war”出現編號為2、8、15、22、68和77的文件上。

    一旦建立了索引,就開始對文件進行等級評定并確定它們的相關性。假如某個人上Google搜索并輸入“civil war”,為呈現和評價搜索結果需要做兩件事:一是查找包含了用戶提問的網頁;二是按照相關性排定匹配網頁的位置。Google已經開發出一個有趣的技術可加速第一步驟的過程:不是將所有索引存儲在一臺電腦上,而是使用數百臺電腦做這種工作。由于任務被分配到很多電腦上,使得查詢答案更為迅速。

    為更加形象地描述這個過程,可以設想下一本30頁厚書的索引。如果一個人在索引中查找數頁的信息,那么每一次搜索都至少需要花幾秒鐘的時間;但如果你將索引的每一頁分給不同的人去查找呢?三十個人分別查找索引的不同部分,要比一個人獨自查找快的多。同樣,Google也是將數據分配到各臺電腦上以便可以更快地查找文件。

    如何查找包含了用戶提問的網頁?讓我們返回到上面舉的“civil war”例子。單詞“civil”在編號為3、8、22、56、68和92的文件上,單詞“war”在編號為2、8、15、22、68和77的文件上,我們可以在網頁上顯示文件并尋找包含兩個單詞的文件(從下表中可以看出是8、22和68號文件)。

    單詞civil 3 8 22 56 68 92

    單詞war 2 8 15 22 68 77

    兩個單詞都出現 8 22 68

    包含了一個單詞的文件列表被稱為“文件標識列表”,查找包含兩個單詞的文件被稱為“文件標識列表的交集”。

    評定搜索結果

    有了包含用戶提問的網頁后,就該按照相關性評定網頁了。Google使用了很多技術,其中 PageRank算法是最有名的。PageRank評定的是兩種事情:從網站到某一網頁有多少個鏈接,提供鏈接的網站的排名。使用PageRank,來自 CNN和紐約時報網站的鏈接的價值,是很多不太有名網站的兩倍。

    除了PageRank外Google還使用了很多其他技術,例如一份文件所包含的 “civil”和“war”兩個單詞靠的很近,就比只使用了“war”單詞的包含“Revolutionary War”(獨立戰爭)的文件相關性要大的多。另外在題目中出現了“civil war”的網頁,它的相關性就比題目為“19th Century American Clothing”(19世紀的美國服裝)要重要的多。同樣如果“civil war”在網頁上出現了數次,比出現一次的網頁要相關的多。

    Google的目的是要找到知名度和相關性都大的網頁。如果兩個網頁出現匹配提問的信息數量幾乎一樣,我們常常會選擇更有名網站的鏈接。但如果其他方面表明一個網頁更為相關,也會選擇更少鏈接或更低排名的網頁。例如,一個網頁全篇都是講“南北戰爭”的內容,會比只是略微提到“南北戰爭”的網頁更為有用,即使這個網頁是出現不太有名的網站上。一旦我們有了文件的列表和分值,就會選擇最高分值、最匹配的文件。

    Google從包含了提問單詞的每一份文件中提取幾句話作為摘要顯示,接著將排好的URLs和摘要顯示在搜索結果上。正如你所知道的運行一個搜索器需要大量的計算資源。每一次搜索需要500臺以上的電腦一起工作,搜索的時間還不到半秒鐘。



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=559502

    posted @ 2005-12-23 14:43 只牽這只狗 閱讀(208) | 評論 (0)編輯 收藏

    快圣誕晚會了,決定出個小節目——準備“嗷嗷”一下,呵.......終于有了點快樂的氣氛.....

    posted @ 2005-12-22 10:27 只牽這只狗 閱讀(190) | 評論 (0)編輯 收藏

         摘要:    觀察家模式是一個事件通知模式,被觀察者發生某個事件,或者狀態發生某個變化,就通知觀察者,這樣觀察者就能采取適當的行動。下面我以一個簡單的例子來說明一下這個模式的應用。 我們都知道,蜜蜂是勤勞的精靈,它總是四處采蜜。只要花朵的花瓣一張開,她就飛上去采蜜。我們輕易就能想到,在這里,蜜蜂應該是一個觀察者,而花朵是一個被觀察者。只要花朵發生花瓣張開事件,就通知了觀...  閱讀全文
    posted @ 2005-12-09 16:26 只牽這只狗 閱讀(336) | 評論 (0)編輯 收藏

    今天測試時出的一個錯誤,數據庫中一個表的說明欄位值全部成了“ui8ll/”,但卻無法再現。很郁悶,搞了半天查不出什么原因。應該是編碼格式出現異常,但什么原因會突然造成編碼異常呢?且把整個這一欄的值全都變了而其他欄位卻正常?是數據庫的原因還是程序原因?
    google一下“ui8ll/”,沒有資料!

    JSP編碼:
    <%@ page contentType = "text/html;charset=GBK"%>
    database是DB2 欄位Type是varchar

    到底是什么原因呢?

    posted @ 2005-12-09 11:29 只牽這只狗 閱讀(191) | 評論 (0)編輯 收藏

    xml(可擴展標記語言)看起來可能像某種w3c標準——現在沒有什么實際影響,即使以后能派上用場,也是很久以后的事。但實際上,它現在已經得到了應用。所以,不要等到xml已被加進了你最喜愛的html編輯器中才開始使用它。它現在就可以解決各種內部問題和b2b系統問題。

    在sparks.com,我們使用xml來標準化從java對象到html數據顯示等不同系統之間的數據表示。

    特別需要指出的是,我們發現,只要以非常基本的xml結構來實現標準化,就可以更容易地共享和操作數據。在這一過程中,我們發現了使用xml的很多有效方法。下面詳細介紹我們現在的應用情況。

    標準化
    在使用xml之前,建立與你要使用的信息不同的xml數據格式。

    生成動態xml
    從數據庫中生成html并不新鮮,但生成xml卻很新鮮。這里我們介紹具體的生成步驟。

    用xsl作為模板語言
    xsl(可擴展樣式表語言)是定義xml數據顯示格式的好方法,如果寫成幾個靜態模板會更有效。

    生成html
    xml加上xsl就等于html。這聽起來似乎不對,但用戶所見的我們的html頁面其實就是xml和xsl共同產生的效果。


    一、標準化

    xml的能力來自于它的靈活性。但不幸的是,它有時太靈活了,以至于你會面對一個空白的頁面,發愁該怎么解決問題。

    在任何xml的項目中,第一步工作都是創建標準的數據格式。為此你要作出以下決定:

    ? 要涉及哪些數據
    ? 是否要使用dtd(文件類型定義)
    ? 是否要使用dom(文檔對象模型)或sax(xml的簡化api)解析

    確定數據:
    因為沒有標準的xml格式,開發者可以自由地開發自己的格式。然而,如果你的格式只能被一個應用程序識別,那么你只能運行這個程序來使用該格式。如果還有其他程序也能讀懂你的xml格式,那顯然會更有幫助。如果某個xml格式被修改,則使用它的系統可能也需要被修改,所以你應該建立盡可能完整的格式。因為大多數系統忽略它們無法識別的標簽,所以改變一個xml格式的最安全的方法是添加標簽,而不是修改標簽。

    單擊此處查看xml數據格式實例

    在sparks.com,我們查看了不同的產品展示需要的所有產品數據。盡管并不是所有的頁面都使用全部數據,但我們還是由此開發出適用于所有數據的非常完整的xml數據格式。例如,我們的產品明細信息頁面顯示的數據要比產品瀏覽頁面多。然而,我們在這兩種情況下仍然使用相同的數據格式,因為每個頁面的xsl模板都只使用它所需要的字段。

    是否使用dtd
    在sparks.com,我們使用組織良好的xml,而不使用僅僅是正確的xml,因為前者不需要dtd。dtd在用戶點擊和看到頁面之間加入了一個處理層。我們發現這一層需要太多的處理。當然,在以xml格式與其他公司通信時,使用dtd還是很不錯的。因為dtd能在發送和接受時能保證數據結構正確。

    選擇解析引擎
    現在,可以使用的解析引擎有好幾個。選擇哪一個幾乎完全取決于你的應用需要。如果你決定使用dtd,那么這個解析引擎必須能使你的xml被dtd驗證。你可以將驗證另放到一個進程中,但那樣會影響性能。

    sax和dom是兩個基本的解析模型。sax基于事件,所以在xml被解析時,事件被發送給引擎。接下來,事件與輸出文件同步。dom解析引擎為動態xml數據和xsl樣式表建立層次樹狀結構。通過隨機訪問dom樹,可以提供xml數據,就象由xsl樣式表來決定一樣。sax模型上的爭論主要集中于對dom結構的內存降低過度和加快xsl樣式表解析時間縮短方面。

    然而,我們發現使用sax的很多系統并沒有充分發揮它的能力。這些系統用它來建立dom結構并通過dom結構來發送事件。用這種方法,在任何xml處理之前必須從樣式表中建立dom,所以性能會下降。

    二、生成動態xml

    一旦建立了xml格式,我們需要一種能夠將其從數據庫中動態移植的方法。

    生成xml文檔相對來說比較簡單,因為它只需要一個可以處理字符串的系統。我們建立了一個使用java servlet、enterprise javabean server、jdbc和rdbms(關系型數據庫管理系統)的系統。

    ? servlet通過把生成xml文檔的任務交給enterprise javabean (ejb)來處理產品信息請求。
    ? ejb使用jdbc從數據庫里查詢所需的產品詳細信息。
    ? ejb生成xml文件并把它傳遞給servlet。
    ? servlet調用解析引擎,從xml文件和靜態的xsl樣式表中創建html輸出。

    (有關xsl應用的其他信息,請參閱用xsl作為模板語言。)

    生成xml的例子
    在java中創建xml文檔字符串的真正代碼可以分成幾個方法和類。

    啟動xml生成過程的代碼放在ejb方法里。這一實例會立即創建一個stringbuffer,以便存儲生成的xml字符串。

    stringbuffer xml = new stringbuffer();
    xml.append(xmlutils.begindocument("/browse_find/browse.xsl", "browse", request));
    xml.append(product.toxml());
    xml.append(xmlutils.enddocument("browse");
    out.print(xml.tostring());


    后面的三個xml.append()變元本身就是對其他方法的調用。
    產生文件頭
    第一個附加方法調用xmlutils類來產生xml文件頭。我們的java servlet中的代碼如下:

    public static string begindocument(string stylesheet, string page)
    {
        stringbuffer xml = new stringbuffer();
        xml.append("\n")
        .append("    .append(stylesheet).append("\"")
        .append(" type =\"text/xsl\"?>\n");
      xml.append("<").append(page).append(">\n");
      return xml.tostring();
    }

    這段代碼生成了xml文件頭。標簽把本文件定義為支持1.0版本的xml文件。第二行代碼指向用以顯示數據的正確樣式表的位置。最后包括進去的是項級標簽(本實例中為)。在文件末尾,只有標簽需要被關閉。

    填入產品信息
    完成了文件頭后,控制方法會調用java對象來產生它的xml。本例中調用的是product對象。product對象使用兩個方法來產生它的xml表示。第一個方法toxml()通過產生標簽來建立product節點。然后它會調用internalxml(),這樣就能提供產品xml所需的內容。internalxml()是一系列的stringbuffer.append()調用。stringbuffer也被轉換成字符串并返回給控制方法。
    public string toxml()
        {
        stringbuffer xml = new stringbuffer("\n");
        xml.append(internalxml());
        xml.append("
    \n");
        return xml.tostring();
        }

    public string internalxml()
        {
        stringbuffer xml = new
        stringbuffer("\t")
            .append(producttype).append("\n");
        xml.append("\t").append(idvalue.trim())
            .append("\n");
        xml.append("\t").append(idname.trim())
            .append("\n");
        xml.append("\t").append(page.trim())
            .append("\n");
    厖?
          xml.append("\t").append(amount).append("\n");
        xml.append("\t").append(vendor).append("\n");
        xml.append("\t\n");
        xml.append("\t").append(pubdesc).append("\n");
        xml.append("\t").append(vendesc).append("\n";
    厖?
        return xml.tostring();
    }


    關閉文件
    最后,xmlutils.enddocument()方法被調用。這個調用關閉xml標簽(本例中為),并最終完成架構好的xml文件。來自控制方法的整個stringbuffer也轉換成字符串,并返回給處理最初http請求的servlet。

    三、用xsl作為模板語言

    為了得到html輸出,我們把生成的xml文件和控制xml數據如何表示的xsl模板相結合。我們的xsl模板由精心組織的xsl和html標簽組成。

    開始建模板
    我們的xsl模板開始部分與下面這段代碼類似。第一行代碼為必需代碼,將本文件定義為xsl樣式表。xmlns:xsl=屬性引用本文件所使用的xml名稱空間,而version=屬性則定義名稱空間的版本號。在文件的末尾,我們關閉標簽。

    開始的第二行代碼確定了xsl模板的模式。match屬性是必需的,在這里指向xml標簽。在我們的系統里,標簽里包含 標簽,這使得xsl模板可以訪問嵌在標簽內的產品信息。我們又一次必須在文件末尾關閉標簽。

    接下來,我們來看一看組織良好的html。由于它將被xml解析引擎處理,所以必須符合組織良好的xml的所有規則。從本質上來講,這意味著所有的開始標簽必須有對應的結束標簽。例如,通常不被結束的

    標簽,必須用

    關閉。
    http://www.w3.org/1999/xsl/transform"
    version="1.0">?br>

    在模板的主體內,有很多xsl標簽被用于為數據表示提供邏輯。下面解釋兩個常用的標簽。
    choose
    標簽類似于傳統編程語言中if-then-else結構的開始部分。在xsl中,choose標簽表示在代碼進入的部分中,賦值將觸發動作的發生。擁有賦值屬性的標簽跟在choose標簽后面。如果賦值是正確的,位于的開始和結束標簽之間的內容將被使用。如果賦值錯誤,就使用的開始和結束標簽之間的內容。整個部分用來結束。

    在這個例子里,when標簽會為quantity標簽檢查xml。如果quantity標簽里含有值為真的error屬性,quantity標簽將會顯示列在下面的表格單元。如果屬性的值不為真,xsl將會顯示otherwise標簽間的內容。在下面的實例里,如果error屬性不真,則什么都不會被顯示。

    posted @ 2005-12-07 11:47 只牽這只狗 閱讀(229) | 評論 (0)編輯 收藏

    java.util 中的集合類包含 Java 中某些最常用的類。 最常用的集合類是 List 和 Map。 List 的具體實現包括 ArrayList 和 Vector,它們是可變大小的列表,比較適合構建、存儲和操作任何類型對象的元素列表。 List 適用于按數值索引訪問元素的情形。

    Map 提供了一個更通用的元素存儲方法。 Map 集合類用于存儲元素對(稱作“鍵”和“值”),其中每個鍵映射到一個值。 從概念上而言,您可以將 List 看作是具有數值鍵的 Map。 而實際上,除了 List 和 Map 都在定義 java.util 中外,兩者并沒有直接的聯系。本文將著重介紹核心 Java 發行套件中附帶的 Map,同時還將介紹如何采用或實現更適用于您應用程序特定數據的專用 Map。

    了解 Map 接口和方法

    Java 核心類中有很多預定義的 Map 類。 在介紹具體實現之前,我們先介紹一下 Map 接口本身,以便了解所有實現的共同點。 Map 接口定義了四種類型的方法,每個 Map 都包含這些方法。 下面,我們從兩個普通的方法(表 1)開始對這些方法加以介紹。

    表 1: 覆蓋的方法。 我們將這 Object 的這兩個方法覆蓋,以正確比較 Map 對象的等價性。 equals(Object o) 比較指定對象與此 Map 的等價性
    hashCode() 返回此 Map 的哈希碼



    Map 構建

    Map 定義了幾個用于插入和刪除元素的變換方法(表 2)。

    表 2: Map 更新方法: 可以更改 Map 內容。 clear() 從 Map 中刪除所有映射
    remove(Object key) 從 Map 中刪除鍵和關聯的值
    put(Object key, Object value) 將指定值與指定鍵相關聯
    clear() 從 Map 中刪除所有映射
    putAll(Map t) 將指定 Map 中的所有映射復制到此 map



    盡管您可能注意到,縱然假設忽略構建一個需要傳遞給 putAll() 的 Map 的開銷,使用 putAll() 通常也并不比使用大量的 put() 調用更有效率,但 putAll() 的存在一點也不稀奇。 這是因為,putAll() 除了迭代 put() 所執行的將每個鍵值對添加到 Map 的算法以外,還需要迭代所傳遞的 Map 的元素。 但應注意,putAll() 在添加所有元素之前可以正確調整 Map 的大小,因此如果您未親自調整 Map 的大小(我們將對此進行簡單介紹),則 putAll() 可能比預期的更有效。

    查看 Map

    迭代 Map 中的元素不存在直接了當的方法。 如果要查詢某個 Map 以了解其哪些元素滿足特定查詢,或如果要迭代其所有元素(無論原因如何),則您首先需要獲取該 Map 的“視圖”。 有三種可能的視圖(參見表 3)

    所有鍵值對 — 參見 entrySet()
    所有鍵 — 參見 keySet()
    所有值 — 參見 values()

    前兩個視圖均返回 Set 對象,第三個視圖返回 Collection 對象。 就這兩種情況而言,問題到這里并沒有結束,這是因為您無法直接迭代 Collection 對象或 Set 對象。要進行迭代,您必須獲得一個 Iterator 對象。 因此,要迭代 Map 的元素,必須進行比較煩瑣的編碼


    Iterator keyValuePairs = aMap.entrySet().iterator();
    Iterator keys = aMap.keySet().iterator();
    Iterator values = aMap.values().iterator();


    值得注意的是,這些對象(Set、Collection 和 Iterator)實際上是基礎 Map 的視圖,而不是包含所有元素的副本。 這使它們的使用效率很高。 另一方面,Collection 或 Set 對象的 toArray() 方法卻創建包含 Map 所有元素的數組對象,因此除了確實需要使用數組中元素的情形外,其效率并不高。

    我運行了一個小測試(隨附文件中的 Test1),該測試使用了 HashMap,并使用以下兩種方法對迭代 Map 元素的開銷進行了比較:


    int mapsize = aMap.size();

    Iterator keyValuePairs1 = aMap.entrySet().iterator();
    for (int i = 0; i < mapsize; i++)
    {
    Map.Entry entry = (Map.Entry) keyValuePairs1.next();
    Object key = entry.getKey();
    Object value = entry.getValue();
    ...
    }

    Object[] keyValuePairs2 = aMap.entrySet().toArray();
    for (int i = 0; i < rem; i++) {
    {
    Map.Entry entry = (Map.Entry) keyValuePairs2[i];
    Object key = entry.getKey();


    Object value = entry.getValue();
    ...
    }


    此測試使用了兩種測量方法: 一種是測量迭代元素的時間,另一種測量使用 toArray 調用創建數組的其他開銷。 第一種方法(忽略創建數組所需的時間)表明,使用已從 toArray 調用中創建的數組迭代元素的速度要比使用 Iterator 的速度大約快 30%-60%。 但如果將使用 toArray 方法創建數組的開銷包含在內,則使用 Iterator 實際上要快 10%-20%。 因此,如果由于某種原因要創建一個集合元素的數組而非迭代這些元素,則應使用該數組迭代元素。 但如果您不需要此中間數組,則不要創建它,而是使用 Iterator 迭代元素。

    表 3: 返回視圖的 Map 方法: 使用這些方法返回的對象,您可以遍歷 Map 的元素,還可以刪除 Map 中的元素。 entrySet() 返回 Map 中所包含映射的 Set 視圖。 Set 中的每個元素都是一個 Map.Entry 對象,可以使用 getKey() 和 getValue() 方法(還有一個 setValue() 方法)訪問后者的鍵元素和值元素
    keySet() 返回 Map 中所包含鍵的 Set 視圖。 刪除 Set 中的元素還將刪除 Map 中相應的映射(鍵和值)
    values() 返回 map 中所包含值的 Collection 視圖。 刪除 Collection 中的元素還將刪除 Map 中相應的映射(鍵和值)



    訪問元素

    表 4 中列出了 Map 訪問方法。Map 通常適合按鍵(而非按值)進行訪問。 Map 定義中沒有規定這肯定是真的,但通常您可以期望這是真的。 例如,您可以期望 containsKey() 方法與 get() 方法一樣快。 另一方面,containsValue() 方法很可能需要掃描 Map 中的值,因此它的速度可能比較慢。

    表 4: Map 訪問和測試方法: 這些方法檢索有關 Map 內容的信息但不更改 Map 內容。 get(Object key) 返回與指定鍵關聯的值
    containsKey(Object key) 如果 Map 包含指定鍵的映射,則返回 true
    containsValue(Object value) 如果此 Map 將一個或多個鍵映射到指定值,則返回 true
    isEmpty() 如果 Map 不包含鍵-值映射,則返回 true
    size() 返回 Map 中的鍵-值映射的數目



    對使用 containsKey() 和 containsValue() 遍歷 HashMap 中所有元素所需時間的測試表明,containsValue() 所需的時間要長很多。 實際上要長幾個數量級! (參見圖 1 和圖 2,以及隨附文件中的 Test2)。 因此,如果 containsValue() 是應用程序中的性能問題,它將很快顯現出來,并可以通過監測您的應用程序輕松地將其識別。 這種情況下,我相信您能夠想出一個有效的替換方法來實現 containsValue() 提供的等效功能。 但如果想不出辦法,則一個可行的解決方案是再創建一個 Map,并將第一個 Map 的所有值作為鍵。 這樣,第一個 Map 上的 containsValue() 將成為第二個 Map 上更有效的 containsKey()。


    圖 1: 使用 JDeveloper 創建并運行 Map 測試類




    圖 2: 在 JDeveloper 中使用執行監測器進行的性能監測查出應用程序中的瓶頸



    核心 Map

    Java 自帶了各種 Map 類。 這些 Map 類可歸為三種類型:


    通用 Map,用于在應用程序中管理映射,通常在 java.util 程序包中實現
    HashMap
    Hashtable
    Properties
    LinkedHashMap
    IdentityHashMap
    TreeMap
    WeakHashMap
    ConcurrentHashMap
    專用 Map,您通常不必親自創建此類 Map,而是通過某些其他類對其進行訪問
    java.util.jar.Attributes
    javax.print.attribute.standard.PrinterStateReasons
    java.security.Provider
    java.awt.RenderingHints
    javax.swing.UIDefaults
    一個用于幫助實現您自己的 Map 類的抽象類
    AbstractMap

    內部哈希: 哈希映射技術

    幾乎所有通用 Map 都使用哈希映射。 這是一種將元素映射到數組的非常簡單的機制,您應了解哈希映射的工作原理,以便充分利用 Map。

    哈希映射結構由一個存儲元素的內部數組組成。 由于內部采用數組存儲,因此必然存在一個用于確定任意鍵訪問數組的索引機制。 實際上,該機制需要提供一個小于數組大小的整數索引值。 該機制稱作哈希函數。 在 Java 基于哈希的 Map 中,哈希函數將對象轉換為一個適合內部數組的整數。 您不必為尋找一個易于使用的哈希函數而大傷腦筋: 每個對象都包含一個返回整數值的 hashCode() 方法。 要將該值映射到數組,只需將其轉換為一個正值,然后在將該值除以數組大小后取余數即可。 以下是一個簡單的、適用于任何對象的 Java 哈希函數


    int hashvalue = Maths.abs(key.hashCode()) % table.length;


    (% 二進制運算符(稱作模)將左側的值除以右側的值,然后返回整數形式的余數。)

    實際上,在 1.4 版發布之前,這就是各種基于哈希的 Map 類所使用的哈希函數。 但如果您查看一下代碼,您將看到


    int hashvalue = (key.hashCode() & 0x7FFFFFFF) % table.length;


    它實際上是使用更快機制獲取正值的同一函數。 在 1.4 版中,HashMap 類實現使用一個不同且更復雜的哈希函數,該函數基于 Doug Lea 的 util.concurrent 程序包(稍后我將更詳細地再次介紹 Doug Lea 的類)。


    圖 3: 哈希工作原理



    該圖介紹了哈希映射的基本原理,但我們還沒有對其進行詳細介紹。 我們的哈希函數將任意對象映射到一個數組位置,但如果兩個不同的鍵映射到相同的位置,情況將會如何? 這是一種必然發生的情況。 在哈希映射的術語中,這稱作沖突。 Map 處理這些沖突的方法是在索引位置處插入一個鏈接列表,并簡單地將元素添加到此鏈接列表。 因此,一個基于哈希的 Map 的基本 put() 方法可能如下所示


    public Object put(Object key, Object value) {
    //我們的內部數組是一個 Entry 對象數組
    //Entry[] table;

    //獲取哈希碼,并映射到一個索引
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % table.length;

    //循環遍歷位于 table[index] 處的鏈接列表,以查明
    //我們是否擁有此鍵項 — 如果擁有,則覆蓋它
    for (Entry e = table[index] ; e != null ; e = e.next) {
    //必須檢查鍵是否相等,原因是不同的鍵對象
    //可能擁有相同的哈希
    if ((e.hash == hash) && e.key.equals(key)) {
    //這是相同鍵,覆蓋該值
    //并從該方法返回 old 值
    Object old = e.value;
    e.value = value;
    return old;
    }
    }

    //仍然在此處,因此它是一個新鍵,只需添加一個新 Entry
    //Entry 對象包含 key 對象、 value 對象、一個整型的 hash、
    //和一個指向列表中的下一個 Entry 的 next Entry

    //創建一個指向上一個列表開頭的新 Entry,
    //并將此新 Entry 插入表中
    Entry e = new Entry(hash, key, value, table[index]);
    table[index] = e;

    return null;
    }



    如果看一下各種基于哈希的 Map 的源代碼,您將發現這基本上就是它們的工作原理。 此外,還有一些需要進一步考慮的事項,如處理空鍵和值以及調整內部數組。 此處定義的 put() 方法還包含相應 get() 的算法,這是因為插入包括搜索映射索引處的項以查明該鍵是否已經存在。 (即 get() 方法與 put() 方法具有相同的算法,但 get() 不包含插入和覆蓋代碼。) 使用鏈接列表并不是解決沖突的唯一方法,某些哈希映射使用另一種“開放式尋址”方案,本文對其不予介紹。

    優化 Hasmap

    如果哈希映射的內部數組只包含一個元素,則所有項將映射到此數組位置,從而構成一個較長的鏈接列表。 由于我們的更新和訪問使用了對鏈接列表的線性搜索,而這要比 Map 中的每個數組索引只包含一個對象的情形要慢得多,因此這樣做的效率很低。 訪問或更新鏈接列表的時間與列表的大小線性相關,而使用哈希函數訪問或更新數組中的單個元素則與數組大小無關 — 就漸進性質(Big-O 表示法)而言,前者為 O(n),而后者為 O(1)。 因此,使用一個較大的數組而不是讓太多的項聚集在太少的數組位置中是有意義的。

    調整 Map 實現的大小

    在哈希術語中,內部數組中的每個位置稱作“存儲桶”(bucket),而可用的存儲桶數(即內部數組的大小)稱作容量 (capacity)。 為使 Map 對象有效地處理任意數目的項,Map 實現可以調整自身的大小。 但調整大小的開銷很大。 調整大小需要將所有元素重新插入到新數組中,這是因為不同的數組大小意味著對象現在映射到不同的索引值。 先前沖突的鍵可能不再沖突,而先前不沖突的其他鍵現在可能沖突。 這顯然表明,如果將 Map 調整得足夠大,則可以減少甚至不再需要重新調整大小,這很有可能顯著提高速度。

    使用 1.4.2 JVM 運行一個簡單的測試,即用大量的項(數目超過一百萬)填充 HashMap。 表 5 顯示了結果,并將所有時間標準化為已預先設置大小的服務器模式(關聯文件中的 Test3)。 對于已預先設置大小的 JVM,客戶端和服務器模式 JVM 運行時間幾乎相同(在放棄 JIT 編譯階段后)。 但使用 Map 的默認大小將引發多次調整大小操作,開銷很大,在服務器模式下要多用 50% 的時間,而在客戶端模式下幾乎要多用兩倍的時間!

    表 5: 填充已預先設置大小的 HashMap 與填充默認大小的 HashMap 所需時間的比較 客戶端模式 服務器模式
    預先設置的大小 100% 100%
    默認大小 294% 157%



    使用負載因子

    為確定何時調整大小,而不是對每個存儲桶中的鏈接列表的深度進行記數,基于哈希的 Map 使用一個額外參數并粗略計算存儲桶的密度。 Map 在調整大小之前,使用名為“負載因子”的參數指示 Map 將承擔的“負載”量,即它的負載程度。 負載因子、項數(Map 大小)與容量之間的關系簡單明了:


    如果(負載因子)x(容量)>(Map 大小),則調整 Map 大小

    例如,如果默認負載因子為 0.75,默認容量為 11,則 11 x 0.75 = 8.25,該值向下取整為 8 個元素。 因此,如果將第 8 個項添加到此 Map,則該 Map 將自身的大小調整為一個更大的值。 相反,要計算避免調整大小所需的初始容量,用將要添加的項數除以負載因子,并向上取整,例如,


    對于負載因子為 0.75 的 100 個項,應將容量設置為 100/0.75 = 133.33,并將結果向上取整為 134(或取整為 135 以使用奇數)

    奇數個存儲桶使 map 能夠通過減少沖突數來提高執行效率。 雖然我所做的測試(關聯文件中的Test4)并未表明質數可以始終獲得更好的效率,但理想情形是容量取質數。 1.4 版后的某些 Map(如 HashMap 和 LinkedHashMap,而非 Hashtable 或 IdentityHashMap)使用需要 2 的冪容量的哈希函數,但下一個最高 2 的冪容量由這些 Map 計算,因此您不必親自計算。

    負載因子本身是空間和時間之間的調整折衷。 較小的負載因子將占用更多的空間,但將降低沖突的可能性,從而將加快訪問和更新的速度。 使用大于 0.75 的負載因子可能是不明智的,而使用大于 1.0 的負載因子肯定是不明知的,這是因為這必定會引發一次沖突。 使用小于 0.50 的負載因子好處并不大,但只要您有效地調整 Map 的大小,應不會對小負載因子造成性能開銷,而只會造成內存開銷。 但較小的負載因子將意味著如果您未預先調整 Map 的大小,則導致更頻繁的調整大小,從而降低性能,因此在調整負載因子時一定要注意這個問題。

    選擇適當的 Map

    應使用哪種 Map? 它是否需要同步? 要獲得應用程序的最佳性能,這可能是所面臨的兩個最重要的問題。 當使用通用 Map 時,調整 Map 大小和選擇負載因子涵蓋了 Map 調整選項。

    以下是一個用于獲得最佳 Map 性能的簡單方法

    將您的所有 Map 變量聲明為 Map,而不是任何具體實現,即不要聲明為 HashMap 或 Hashtable,或任何其他 Map 類實現。


    Map criticalMap = new HashMap(); //好

    HashMap criticalMap = new HashMap(); //差


    這使您能夠只更改一行代碼即可非常輕松地替換任何特定的 Map 實例。

    下載 Doug Lea 的 util.concurrent 程序包 (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html)。 將 ConcurrentHashMap 用作默認 Map。 當移植到 1.5 版時,將 java.util.concurrent.ConcurrentHashMap 用作您的默認 Map。 不要將 ConcurrentHashMap 包裝在同步的包裝器中,即使它將用于多個線程。 使用默認大小和負載因子。
    監測您的應用程序。 如果發現某個 Map 造成瓶頸,則分析造成瓶頸的原因,并部分或全部更改該 Map 的以下內容: Map 類;Map 大小;負載因子;關鍵對象 equals() 方法實現。 專用的 Map 的基本上都需要特殊用途的定制 Map 實現,否則通用 Map 將實現您所需的性能目標。

    Map 選擇

    也許您曾期望更復雜的考量,而這實際上是否顯得太容易? 好的,讓我們慢慢來。 首先,您應使用哪種 Map? 答案很簡單: 不要為您的設計選擇任何特定的 Map,除非實際的設計需要指定一個特殊類型的 Map。 設計時通常不需要選擇具體的 Map 實現。 您可能知道自己需要一個 Map,但不知道使用哪種。 而這恰恰就是使用 Map 接口的意義所在。 直到需要時再選擇 Map 實現 — 如果隨處使用“Map”聲明的變量,則更改應用程序中任何特殊 Map 的 Map 實現只需要更改一行,這是一種開銷很少的調整選擇。 是否要使用默認的 Map 實現? 我很快將談到這個問題。

    同步 Map

    同步與否有何差別? (對于同步,您既可以使用同步的 Map,也可以使用 Collections.synchronizedMap() 將未同步的 Map 轉換為同步的 Map。 后者使用“同步的包裝器”)這是一個異常復雜的選擇,完全取決于您如何根據多線程并發訪問和更新使用 Map,同時還需要進行維護方面的考慮。 例如,如果您開始時未并發更新特定 Map,但它后來更改為并發更新,情況將如何? 在這種情況下,很容易在開始時使用一個未同步的 Map,并在后來向應用程序中添加并發更新線程時忘記將此未同步的 Map 更改為同步的 Map。 這將使您的應用程序容易崩潰(一種要確定和跟蹤的最糟糕的錯誤)。 但如果默認為同步,則將因隨之而來的可怕性能而序列化執行多線程應用程序。 看起來,我們需要某種決策樹來幫助我們正確選擇。

    Doug Lea 是紐約州立大學奧斯威戈分校計算機科學系的教授。 他創建了一組公共領域的程序包(統稱 util.concurrent),該程序包包含許多可以簡化高性能并行編程的實用程序類。 這些類中包含兩個 Map,即 ConcurrentReaderHashMap 和 ConcurrentHashMap。 這些 Map 實現是線程安全的,并且不需要對并發訪問或更新進行同步,同時還適用于大多數需要 Map 的情況。 它們還遠比同步的 Map(如 Hashtable)或使用同步的包裝器更具伸縮性,并且與 HashMap 相比,它們對性能的破壞很小。 util.concurrent 程序包構成了 JSR166 的基礎;JSR166 已經開發了一個包含在 Java 1.5 版中的并發實用程序,而 Java 1.5 版將把這些 Map 包含在一個新的 java.util.concurrent 程序包中。

    所有這一切意味著您不需要一個決策樹來決定是使用同步的 Map 還是使用非同步的 Map, 而只需使用 ConcurrentHashMap。 當然,在某些情況下,使用 ConcurrentHashMap 并不合適。 但這些情況很少見,并且應具體情況具體處理。 這就是監測的用途。


    結束語

    通過 Oracle JDeveloper 可以非常輕松地創建一個用于比較各種 Map 性能的測試類。 更重要的是,集成良好的監測器可以在開發過程中快速、輕松地識別性能瓶頸 - 集成到 IDE 中的監測器通常被較頻繁地使用,以便幫助構建一個成功的工程。 現在,您已經擁有了一個監測器并了解了有關通用 Map 及其性能的基礎知識,可以開始運行您自己的測試,以查明您的應用程序是否因 Map 而存在瓶頸以及在何處需要更改所使用的 Map。

    以上內容介紹了通用 Map 及其性能的基礎知識。 當然,有關特定 Map 實現以及如何根據不同的需求使用它們還存在更多復雜和值得關注的事項,這些將在本文第 2 部分中介紹。


    --------------------------------------------------------------------------------
    Jack Shirazi 是 O''Reilly 的“Java 性能調整”的作者,以及受歡迎的 JavaPerformanceTuning.com 網站(提供 Java 性能信息的全球知名站點)的總監。 Jack 在 Java 性能領域提供咨詢并著書立說。 他還監督 JavaPerformanceTuning.com 提供的信息,其中包括每年大約發布 1000 條性能技巧以及許多有關性能工具、討論組等內容的文章。 Jack 早年還曾發布有關蛋白質結構預測以及黑洞熱力學方面的文章,而且在其空閑時還對某些 Perl5 核心模塊作出了貢獻。

    posted @ 2005-12-06 13:16 只牽這只狗 閱讀(621) | 評論 (0)編輯 收藏

    原著:Steve Mansour
    sman@scruznet.com
    Revised: June 5, 1999
    (copied by jm /at/ jmason.org from http://www.scruz.net/%7esman/regexp.htm, after the original disappeared! )

    翻譯:Neo Lee
    什么是正則表達式

    一個正則表達式,就是用某種模式去匹配一類字符串的一個公式。很多人因為它們看上去比較古怪而且復雜所以不敢去使用——很不幸,這篇文章也不能夠改變這一點,不過,經過一點點練習之后我就開始覺得這些復雜的表達式其實寫起來還是相當簡單的,而且,一旦你弄懂它們,你就能把數小時辛苦而且易錯的文本處理工作壓縮在幾分鐘(甚至幾秒鐘)內完成。正則表達式被各種文本編輯軟件、類庫(例如Rogue Wave的tools.h++)、腳本工具(像awk/grep/sed)廣泛的支持,而且像Microsoft的Visual C++這種交互式IDE也開始支持它了。

    我們將在如下的章節中利用一些例子來解釋正則表達式的用法,絕大部分的例子是基于vi中的文本替換命令和grep文件搜索命令來書寫的,不過它們都是比較典型的例子,其中的概念可以在sed、awk、perl和其他支持正則表達式的編程語言中使用。你可以看看不同工具中的正則表達式這一節,其中有一些在別的工具中使用正則表達式的例子。還有一個關于vi中文本替換命令(s)的簡單說明附在文后供參考。

    正則表達式基礎

    正則表達式由一些普通字符和一些元字符(metacharacters)組成。普通字符包括大小寫的字母和數字,而元字符則具有特殊的含義,我們下面會給予解釋。

    在最簡單的情況下,一個正則表達式看上去就是一個普通的查找串。例如,正則表達式"testing"中沒有包含任何元字符,,它可以匹配"testing"和"123testing"等字符串,但是不能匹配"Testing"。

    要想真正的用好正則表達式,正確的理解元字符是最重要的事情。下表列出了所有的元字符和對它們的一個簡短的描述。

    元字符   描述


    .
    匹配任何單個字符。例如正則表達式r.t匹配這些字符串:ratrutr t,但是不匹配root。 
    $
    匹配行結束符。例如正則表達式weasel$ 能夠匹配字符串"He's a weasel"的末尾,但是不能匹配字符串"They are a bunch of weasels."。 
    ^
    匹配一行的開始。例如正則表達式^When in能夠匹配字符串"When in the course of human events"的開始,但是不能匹配"What and When in the"。
    *
    匹配0或多個正好在它之前的那個字符。例如正則表達式.*意味著能夠匹配任意數量的任何字符。
    \
    這是引用府,用來將這里列出的這些元字符當作普通的字符來進行匹配。例如正則表達式\$被用來匹配美元符號,而不是行尾,類似的,正則表達式\.用來匹配點字符,而不是任何字符的通配符。
    [ ] 
    [c1-c2]
    [^c1-c2]
    匹配括號中的任何一個字符。例如正則表達式r[aou]t匹配ratrotrut,但是不匹配ret。可以在括號中使用連字符-來指定字符的區間,例如正則表達式[0-9]可以匹配任何數字字符;還可以制定多個區間,例如正則表達式[A-Za-z]可以匹配任何大小寫字母。另一個重要的用法是“排除”,要想匹配除了指定區間之外的字符——也就是所謂的補集——在左邊的括號和第一個字符之間使用^字符,例如正則表達式[^269A-Z] 將匹配除了2、6、9和所有大寫字母之外的任何字符。
    \< \>
    匹配詞(word)的開始(\<)和結束(\>)。例如正則表達式\<the能夠匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:這個元字符不是所有的軟件都支持的。
    \( \)
    將 \( 和 \) 之間的表達式定義為“組”(group),并且將匹配這個表達式的字符保存到一個臨時區域(一個正則表達式中最多可以保存9個),它們可以用 \1\9 的符號來引用。
    |
    將兩個匹配條件進行邏輯“或”(Or)運算。例如正則表達式(him|her) 匹配"it belongs to him"和"it belongs to her",但是不能匹配"it belongs to them."。注意:這個元字符不是所有的軟件都支持的。
    +
    匹配1或多個正好在它之前的那個字符。例如正則表達式9+匹配9、99、999等。注意:這個元字符不是所有的軟件都支持的。
    ?
    匹配0或1個正好在它之前的那個字符。注意:這個元字符不是所有的軟件都支持的。
    \{i\}
    \{i,j\}
    匹配指定數目的字符,這些字符是在它之前的表達式定義的。例如正則表達式A[0-9]\{3\} 能夠匹配字符"A"后面跟著正好3個數字字符的串,例如A123、A348等,但是不匹配A1234。而正則表達式[0-9]\{4,6\} 匹配連續的任意4個、5個或者6個數字字符。注意:這個元字符不是所有的軟件都支持的。


    最簡單的元字符是點,它能夠匹配任何單個字符(注意包括新行符)。假定有個文件test.txt包含以下幾行內容:

      he is a rat
      he is in a rut
      the food is Rotten
      I like root beer

    我們可以使用grep命令來測試我們的正則表達式,grep命令使用正則表達式去嘗試匹配指定文件的每一行,并將至少有一處匹配表達式的所有行顯示出來。命令

      grep r.t test.txt

    在test.txt文件中的每一行中搜索正則表達式r.t,并打印輸出匹配的行。正則表達式r.t匹配一個r接著任何一個字符再接著一個t。所以它將匹配文件中的ratrut,而不能匹配Rotten中的Rot,因為正則表達式是大小寫敏感的。要想同時匹配大寫和小寫字母,應該使用字符區間元字符(方括號)。正則表達式[Rr]能夠同時匹配Rr。所以,要想匹配一個大寫或者小寫的r接著任何一個字符再接著一個t就要使用這個表達式:[Rr].t

    要想匹配行首的字符要使用抑揚字符(^)——又是也被叫做插入符。例如,想找到text.txt中行首"he"打頭的行,你可能會先用簡單表達式he,但是這會匹配第三行的the,所以要使用正則表達式^he,它只匹配在行首出現的h

    有時候指定“除了×××都匹配”會比較容易達到目的,當抑揚字符(^)出現在方括號中是,它表示“排除”,例如要匹配he ,但是排除前面是t or s的情性(也就是theshe),可以使用:[^st]he

    可以使用方括號來指定多個字符區間。例如正則表達式[A-Za-z]匹配任何字母,包括大寫和小寫的;正則表達式[A-Za-z][A-Za-z]* 匹配一個字母后面接著0或者多個字母(大寫或者小寫)。當然我們也可以用元字符+做到同樣的事情,也就是:[A-Za-z]+ ,和[A-Za-z][A-Za-z]*完全等價。但是要注意元字符+ 并不是所有支持正則表達式的程序都支持的。關于這一點可以參考后面的正則表達式語法支持情況

    要指定特定數量的匹配,要使用大括號(注意必須使用反斜杠來轉義)。想匹配所有1001000的實例而排除1010000,可以使用:10\{2,3\},這個正則表達式匹配數字1后面跟著2或者3個0的模式。在這個元字符的使用中一個有用的變化是忽略第二個數字,例如正則表達式0\{3,\} 將匹配至少3個連續的0。

    簡單的例子

    這里有一些有代表性的、比較簡單的例子。

    vi 命令 作用


    :%s/ */ /g 把一個或者多個空格替換為一個空格。
    :%s/ *$// 去掉行尾的所有空格。
    :%s/^/ / 在每一行頭上加入一個空格。
    :%s/^[0-9][0-9]* // 去掉行首的所有數字字符。
    :%s/b[aeio]g/bug/g 將所有的bagbegbigbog改為bug。 
    :%s/t\([aou]\)g/h\1t/g 將所有tagtogtug分別改為hathothug(注意用group的用法和使用\1引用前面被匹配的字符)。

    中級的例子(神奇的咒語)

    例1

    將所有方法foo(a,b,c)的實例改為foo(b,a,c)。這里a、b和c可以是任何提供給方法foo()的參數。也就是說我們要實現這樣的轉換:

    之前   之后
    foo(10,7,2) foo(7,10,2)
    foo(x+13,y-2,10) foo(y-2,x+13,10)
    foo( bar(8), x+y+z, 5) foo( x+y+z, bar(8), 5)

    下面這條替換命令能夠實現這一魔法:

      :%s/foo(\([^,]*\),\([^,]*\),\([^)]*\))/foo(\2,\1,\3)/g

    現在讓我們把它打散來加以分析。寫出這個表達式的基本思路是找出foo()和它的括號中的三個參數的位置。第一個參數是用這個表達式來識別的::\([^,]*\),我們可以從里向外來分析它: 

    [^,]   除了逗號之外的任何字符
    [^,]* 0或者多個非逗號字符
    \([^,]*\) 將這些非逗號字符標記為\1,這樣可以在之后的替換模式表達式中引用它
    \([^,]*\), 我們必須找到0或者多個非逗號字符后面跟著一個逗號,并且非逗號字符那部分要標記出來以備后用。

    現在正是指出一個使用正則表達式常見錯誤的最佳時機。為什么我們要使用[^,]*這樣的一個表達式,而不是更加簡單直接的寫法,例如:.*,來匹配第一個參數呢?設想我們使用模式.*來匹配字符串"10,7,2",它應該匹配"10,"還是"10,7,"?為了解決這個兩義性(ambiguity),正則表達式規定一律按照最長的串來,在上面的例子中就是"10,7,",顯然這樣就找出了兩個參數而不是我們期望的一個。所以,我們要使用[^,]*來強制取出第一個逗號之前的部分。

    這個表達式我們已經分析到了:foo(\([^,]*\),這一段可以簡單的翻譯為“當你找到foo(就把其后直到第一個逗號之前的部分標記為\1”。然后我們使用同樣的辦法標記第二個參數為\2。對第三個參數的標記方法也是一樣,只是我們要搜索所有的字符直到右括號。我們并沒有必要去搜索第三個參數,因為我們不需要調整它的位置,但是這樣的模式能夠保證我們只去替換那些有三個參數的foo()方法調用,在foo()是一個重載(overoading)方法時這種明確的模式往往是比較保險的。然后,在替換部分,我們找到foo()的對應實例,然后利用標記好的部分進行替換,是的第一和第二個參數交換位置。

    例2

    假設有一個CSV(comma separated value)文件,里面有一些我們需要的信息,但是格式卻有問題,目前數據的列順序是:姓名,公司名,州名縮寫,郵政編碼,現在我們希望講這些數據重新組織,以便在我們的某個軟件中使用,需要的格式為:姓名,州名縮寫-郵政編碼,公司名。也就是說,我們要調整列順序,還要合并兩個列來構成一個新列。另外,我們的軟件不能接受逗號前后面有任何空格(包括空格和制表符)所以我們還必須要去掉逗號前后的所有空格。

    這里有幾行我們現在的數據:

      Bill Jones,     HI-TEK Corporation ,  CA, 95011
      Sharon Lee Smith,  Design Works Incorporated,  CA, 95012
      B. Amos   ,  Hill Street Cafe,  CA, 95013
      Alexander Weatherworth,  The Crafts Store,  CA, 95014
      ...

    我們希望把它變成這個樣子:

      Bill Jones,CA 95011,HI-TEK Corporation
      Sharon Lee Smith,CA 95012,Design Works Incorporated
      B. Amos,CA 95013,Hill Street Cafe
      Alexander Weatherworth,CA 95014,The Crafts Store
      ...

    我們將用兩個正則表達式來解決這個問題。第一個移動列和合并列,第二個用來去掉空格。

    下面就是第一個替換命令:

      :%s/\([^,]*\),\([^,]*\),\([^,]*\),\(.*\)/\1,\3 \4,\2/

    這里的方法跟例1基本一樣,第一個列(姓名)用這個表達式來匹配:\([^,]*\),即第一個逗號之前的所有字符,而姓名內容被用\1標記下來。公司名和州名縮寫字段用同樣的方法標記為\2\3,而最后一個字段用\(.*\)來匹配("匹配所有字符直到行末")。替換部分則引用上面標記的那些內容來進行構造。

    下面這個替換命令則用來去除空格:

      :%s/[ \t]*,[ \t]*/,/g

    我們還是分解來看:[ \t]匹配空格/制表符,[ \t]* 匹配0或多個空格/制表符,[ \t]*,匹配0或多個空格/制表符后面再加一個逗號,最后,[ \t]*,[ \t]*匹配0或多個空格/制表符接著一個逗號再接著0或多個空格/制表符。在替換部分,我們簡單的我們找到的所有東西替換成一個逗號。這里我們使用了結尾的可選的g參數,這表示在每行中對所有匹配的串執行替換(而不是缺省的只替換第一個匹配串)。

    例3

    假設有一個多字符的片斷重復出現,例如:

    Billy tried really hard
    Sally tried really really hard
    Timmy tried really really really hard
    Johnny tried really really really really hard

    而你想把"really"、"really really",以及任意數量連續出現的"really"字符串換成一個簡單的"very"(simple is good!),那么以下命令:

    :%s/\(really \)\(really \)*/very /

    就會把上述的文本變成:

    Billy tried very hard
    Sally tried very hard
    Timmy tried very hard
    Johnny tried very hard

    表達式\(really \)*匹配0或多個連續的"really "(注意結尾有個空格),而\(really \)\(really \)* 匹配1個或多個連續的"really "實例。

    困難的例子(不可思議的象形文字)

    Coming soon.


    不同工具中的正則表達式

    OK,你已經準備使用RE(regular expressions,正則表達式),但是你并準備使用vi。所以,在這里我們給出一些在其他工具中使用RE的例子。另外,我還會總結一下你在不同程序之間使用RE可能發現的區別。

    當然,你也可以在Visual C++編輯器中使用RE。選擇Edit->Replace,然后選擇"Regular expression"選擇框,Find What輸入框對應上面介紹的vi命令:%s/pat1/pat2/g中的pat1部分,而Replace輸入框對應pat2部分。但是,為了得到vi的執行范圍和g選項,你要使用Replace All或者適當的手工Find Next and Replace(譯者按:知道為啥有人罵微軟弱智了吧,雖然VC中可以選中一個范圍的文本,然后在其中執行替換,但是總之不夠vi那么靈活和典雅)。

    sed

    Sed是Stream EDitor的縮寫,是Unix下常用的基于文件和管道的編輯工具,可以在手冊中得到關于sed的詳細信息。

    這里是一些有趣的sed腳本,假定我們正在處理一個叫做price.txt的文件。注意這些編輯并不會改變源文件,sed只是處理源文件的每一行并把結果顯示在標準輸出中(當然很容易使用重定向來定制):

    sed腳本   描述


    sed 's/^$/d' price.txt 刪除所有空行
    sed 's/^[ \t]*$/d' price.txt 刪除所有只包含空格或者制表符的行
    sed 's/"http://g' price.txt 刪除所有引號

    awk

    awk是一種編程語言,可以用來對文本數據進行復雜的分析和處理。可以在手冊中得到關于awk的詳細信息。這個古怪的名字是它作者們的姓的縮寫(Aho,Weinberger和Kernighan)。

    在Aho,Weinberger和Kernighan的書The AWK Programming Language中有很多很好的awk的例子,請不要讓下面這些微不足道的腳本例子限制你對awk強大能力的理解。我們同樣假定我們針對price.txt文件進行處理,跟sed一樣,awk也只是把結果顯示在終端上。 

    awk腳本   描述


    awk '$0 !~ /^$/' price.txt 刪除所有空行
    awk 'NF > 0' price.txt awk中一個更好的刪除所有行的辦法
    awk '$2 ~ /^[JT]/ {print $3}' price.txt 打印所有第二個字段是'J'或者'T'打頭的行中的第三個字段
    awk '$2 !~ /[Mm]isc/ {print $3 + $4}' price.txt 針對所有第二個字段不包含'Misc'或者'misc'的行,打印第3和第4列的和(假定為數字)
    awk '$3 !~ /^[0-9]+\.[0-9]*$/ {print $0}' price.txt 打印所有第三個字段不是數字的行,這里數字是指d.d或者d這樣的形式,其中d是0到9的任何數字
    awk '$2 ~ /John|Fred/ {print $0}' price.txt 如果第二個字段包含'John'或者'Fred'則打印整行

    grep

    grep是一個用來在一個或者多個文件或者輸入流中使用RE進行查找的程序。它的name編程語言可以用來針對文件和管道進行處理。可以在手冊中得到關于grep的完整信息。這個同樣古怪的名字來源于vi的一個命令,g/re/p,意思是global regular expression print。

    下面的例子中我們假定在文件phone.txt中包含以下的文本,——其格式是姓加一個逗號,然后是名,然后是一個制表符,然后是電話號碼:

      Francis, John           5-3871
      Wong, Fred              4-4123
      Jones, Thomas           1-4122
      Salazar, Richard        5-2522

    grep命令   描述


    grep '\t5-...1' phone.txt 把所有電話號碼以5開頭以1結束的行打印出來,注意制表符是用\t表示的
    grep '^S[^ ]* R' phone.txt 打印所有姓以S打頭和名以R打頭的行
    grep '^[JW]' phone.txt 打印所有姓開頭是J或者W的行
    grep ', ....\t' phone.txt 打印所有姓是4個字符的行,注意制表符是用\t表示的
    grep -v '^[JW]' phone.txt 打印所有不以J或者W開頭的行
    grep '^[M-Z]' phone.txt 打印所有姓的開頭是M到Z之間任一字符的行
    grep '^[M-Z].*[12]' phone.txt 打印所有姓的開頭是M到Z之間任一字符,并且點號號碼結尾是1或者2的行

    egrep

    egrep是grep的一個擴展版本,它在它的正則表達式中支持更多的元字符。下面的例子中我們假定在文件phone.txt中包含以下的文本,——其格式是姓加一個逗號,然后是名,然后是一個制表符,然后是電話號碼:

      Francis, John           5-3871
      Wong, Fred              4-4123
      Jones, Thomas           1-4122
      Salazar, Richard        5-2522

    egrep command   Description


    egrep '(John|Fred)' phone.txt 打印所有包含名字John或者Fred的行
    egrep 'John|22$|^W' phone.txt 打印所有包含John 或者以22結束或者以W的行
    egrep 'net(work)?s' report.txt 從report.txt中找到所有包含networks或者nets的行


    正則表達式語法支持情況

    命令或環境 . [ ] ^ $ \( \) \{ \} ? + | ( )
    vi  X   X   X   X   X           
    Visual C++  X   X   X   X   X           
    awk  X   X   X   X       X   X   X   X 
    sed  X   X   X   X   X   X         
    Tcl  X   X   X   X   X     X   X   X   X 
    ex  X   X   X   X   X   X         
    grep  X   X   X   X   X   X         
    egrep  X   X  X   X   X     X   X   X   X 
    fgrep  X   X   X   X   X           
    perl  X  X  X  X  X    X  X  X  X

     


    vi替換命令簡介

    Vi的替換命令:

      :ranges/pat1/pat2/g

    其中

      : 這是Vi的命令執行界面。
      range 是命令執行范圍的指定,可以使用百分號(%)表示所有行,使用點(.)表示當前行,使用美元符號($)表示最后一行。你還可以使用行號,例如10,20表示第10到20行,.,$表示當前行到最后一行,.+2,$-5表示當前行后兩行直到全文的倒數第五行,等等。

      s 表示其后是一個替換命令。

      pat1 這是要查找的一個正則表達式,這篇文章中有一大堆例子。

      pat2 這是希望把匹配串變成的模式的正則表達式,這篇文章中有一大堆例子。

      g 可選標志,帶這個標志表示替換將針對行中每個匹配的串進行,否則則只替換行中第一個匹配串。

    網上有很多vi的在線手冊,你可以訪問他們以獲得更加完整的信息。



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=539524

    posted @ 2005-12-06 09:25 只牽這只狗 閱讀(197) | 評論 (0)編輯 收藏

         摘要: Posted on 2005-11-24 00:21 BlueO2 閱讀(469) 評論(0)  編輯 收藏 收藏至365Key 所屬分類: AJAX --> 本想翻譯IBM的一篇文章 Build apps using Asynchronous JavaScript with XML 但是發現不如就按照那個方式想怎么寫就怎么寫。之后有時間了會把其中的一個系列...  閱讀全文
    posted @ 2005-12-05 17:12 只牽這只狗 閱讀(355) | 評論 (0)編輯 收藏

    瀏覽器端框架被劃分成兩大類:

    ·應用程序框架:提供瀏覽器的功能,但是常以包括窗口小部件抽象和另外的部件而出名,其功能主要圍繞桌面GUI框架。

    ·基本結構框架:提供基本的管道和可移植的瀏覽器抽象,讓開發者去創建內容。典型的功能:

    * 針對XMLHttpRequest的包裝器以封裝瀏覽器-服務器的交互。(所有的框架都提供這一功能)。

    * XML操作和查詢。

    * 根據來自XMLHttpRequest的應答執行DOM操作。

    * 在一些情況中,與另外的瀏覽器端技術如Flash(和潛在的Java applets)集成在一起。

    而服務器端框架通常以下面兩種方式工作(盡管它們在這里根據語言的不同進行了分類):

    ·HTML/JS生成:服務器提供完整的HTML/Javascript代碼生成和瀏覽器-服務器協調,結果是只有瀏覽器端編碼可以被定制。

    ·遠程調用:Javascript調用直接被路由到服務器端功能(例如Java方法)并返回到Javascript回叫處理器;或者Javascript調用服務器以提取信息,例如會話細節,數據庫查詢等。

    ·純Javascript:應用程序框架

    1.1 Bindows(自從2003年)

    網址是:http://www.bindows.net,Bindows是一個軟件開發包(SDK),它,通過強力聯合DHTML,JavaScript,CSS和XML等技術,能生成高度交互的互聯網應用程序-成為現代的桌面應用程序的強有力對手。Bindows應用程序不要求下載和也不需要在用戶端安裝-僅要求有一個瀏覽器(也不需要Java,Flash或者ActiveX)。Bindows有可能領導面向對象開發的AJAX應用程序的平臺。

    ·它是商業化的,使用來自于MB的技術(總部位于GA USA,主要開發中心在瑞典,成立于2002年)。

    Bindows框架提供給你:

    ·基于類的面向對象的API

    ·一套完整的窗口系統,提供寬范圍的窗口小部件支持,包括菜單、表單、格子、滑動條、量程,甚至更多

    ·用于開發zero-footprint SOA客戶端應用程序的領先的工具箱

    ·本機的XML,SOAP和XML-RPC支持

    ·單用戶到企業級的支持

    ·內建的對AJAX的支持

    Bindows開發環境:

    ·支持企業級規模的工程開發

    ·跨瀏覽器,跨平臺支持

    ·服務器獨立結構

    ·與新的和現有資源的互操作性

    ·一致性開發方法學

    1.2 BackBase(自從2003年)

    網址是:http://www.backbase.com,是一個全面的瀏覽器端框架,支持豐富的瀏覽器功能以及與.NET和Java的集成。

    ·商業化,來自于Backbase B.V(總部在Amsterdam,成立于2003年)。

    1.3 DOJO(開發中;自從2004年9月)

    網址是:http://dojotoolkit.org/,提供全面窗口小組件和瀏覽器-服務器消息支持。

    ·為創建定制的Javascript窗口小組件提供框架支持。

    ·預置的窗口小組件庫。

    ·瀏覽器-服務器消息支持-XMLHttpRequest和另外的機制。

    ·支持瀏覽器中的URL操縱功能。

    ·開源許可(學術自由許可2.1(http://opensource.org/licenses/afl-2.1.php)),由JotSpot(http://www.jot.com/)的Alex Russell(http://alex.dojotoolkit.org/)所領導。

    1.4 Open Rico(開發中;自從2005年5月;基于早期的私有框架)

    網址是:http://openrico.org/demos.page,是一多用途框架,支持Ajax基礎結構和用戶交互。

    ·一個XMLHttpRequest應答能被路由到一個或者更多回叫操作,DOM對象,或者Javascript對象。

    ·容易鼠標拖動支持。

    ·Ajax動畫,例如縮放和變換。

    ·"行為"-實質上是窗口小組件庫。

    ·使用指南(http://www.mirimar.net/mailbrowser/),由RussMirimar的Yonah所提供

    ·開源。源于Sabre航空公司解決方案,由Bill Scott(http://looksgoodworkswell.blogspot.com),Darren James及另外一些人所支持。

    1.5 qooxdoo(開發中;自從2005年5月)

    網址是:http://qooxdoo.sourceforge.net/,是另一個雄心勃勃的框架,提供寬范圍的UI支持和正在開發中的基礎結構特性。

    ·基礎結構:

    * DOM和事件/焦點管理的可移植的抽象。

    * 調試支持。

    * 易于時間調度的Timer類。

    * Getter/Setter支持。

    ·UI:

    * 窗口小組件框架和預置的窗口小組件庫。

    * 布局管理器。

    * 圖像緩沖和可移植的PNG透明性。

    ·開源(LGPL)。來自多方面的貢獻者。

    1.6 Tibet(開發中;自從2005年6月)

    網址是:http://www.technicalpursuit.com/,目的是提供高度可移植的和全面的Javascript API,結果是,可能自動生成大量的客戶端代碼。自稱是"企業級Ajax"。

    ·遠程腳本運行在XMLHttpRequest包裝之上-通過協調調用結果支持工作流管理,例如應答可以發生在只有當兩個分離的調用返回時。

    ·URI支持。

    ·所有的HTTP方法-不僅是"GET"和"POST"。

    ·低級的協議-File://和WebDav以及HTTP。

    ·Web服務調用-SOAP,XML-RPC,等等。

    ·預置的針對Google API,Amazon API等等服務的支持。

    ·由高級Javascript對象組成一個巨大的庫。

    ·許多XML操作。

    ·IDE和開發工具。

    ·開源許可(顯然經過OSI認證,但是細節不多)。

    2 純Javascript:基礎結構框架

    2.1 AjaxCaller(Alpha版本;自從5月2005年)

    網址是:http://ajaxify.com/run/testAjaxCaller/,是一基本的線程安全的XMLHttpRequest包裝器,主要針對Ajax新手,仍處于原始的alpha開發階段,目前僅與AjaxPatterns的在線搜索范例一起打包。

    ·實現對服務器的調用(GET/POST/PUT/DELETE),用路由到一個回叫操作的plain-text或者XML完成。

    ·使用過的XMLHttpRequest對象的析構。

    ·Response緩沖(計劃的)。

    ·針對Ajax新手-并非強調性能優化,該庫主要用于實現易讀的基礎代碼并將提供調試支持。

    ·開源許可。由Michael Mahemoff(http://softwareas.com)(具有John Wehr和Richard Schwartz的一些思想)維護。

    2.2 Flash JavaScript集成包

    網址是:http://www.osflash.org/doku.php?id=flashjs,允許JavaScript和Flash內容的集成:

    ·使JavaScript能夠調用ActionScript功能和反過來的實現。

    ·所有主要的數據類型能在這兩種環境之間傳遞。

    ·開源許可。由多個開源Flash貢獻者提供支持。

    2.3 Google AJAXSLT(發行于2005年6月)

    網址是:http://goog-ajaxslt.sourceforge.net/,是一個Javascript框架,用來執行XSLT轉換以及XPath查詢。

    ·建立在Google地圖工作基礎之上。

    ·開源許可(BSD)。由一家創新搜索方案公司支持,自稱為"Google"。

    2.4 HTMLHttpRequest(Beta版;始于2005年)

    HtmlHttpRequest(http://www.twinhelix.com/javascript/htmlhttprequest/),它使用了XMLHttpRequest和Iframes以改進兼容性。

    ·測試過并能工作在:IE6/Win,IE5.5/Win,IE5/Win,IE4/Win,Mozilla/Win,Opera7/Win,Safari/Mac,IE5/Mac。

    ·未測試,可能能工作在:IE4/Mac,Mozilla/Mac,Opera/Other,Konqueror/Linux。你正在使用這些之一嗎?作者正在請求兼容性信息。

    ·開源許可(LGPL)。由Twin Helix Designs(http://www.twinhelix.com/)的Angus Turnbull維護。

    2.5 交互式網站框架(自從2005年5月)

    交互式網站框架(http://sourceforge.net/projects/iwf/,是一個項目,目的是從瀏覽器端對Ajax基礎結構的多方面予以支持。自描述為"使用javascript,css,xml,和html來創造高度交互網站的框架。包括一個定制的針對高度可讀的javascript的xml分析器。實質上,是建立基于AJAX的網站的基礎,還有另外一些通用腳本"。

    ·線程安全的XMLHttpRequest實現。

    ·針對XML文檔的包裝器,以便你能夠創建更具可讀性的代碼:

    var node = doc.groceries.frozen[0].pizza[0].size;</pre>

    代替手工的導航:

    var node = doc.documentElement.firstChild.firstChild.getAttribute("size");</pre>

    ·開源許可。由Weaver(http://circaware.com|Brock)維護。

    2.6 LibXMLHttpRequest(發行于2003年6月)

    libXmlRequest(http://www.whitefrost.com/servlet/connector?file=reference/2003/06/17/libXmlRequest.html),是XMLHttpRequest的一個瘦包裝器。

    ·getXML()和postXML()方法。

    ·XMLHttpRequest對象池支持。

    ·Response緩沖。

    ·可用源碼(明顯),但是受標準版權的保護,由Stephen W.Coate(http://www.whitefrost.com/index.jsp)所維護。

    2.7 RSLite(x)

    網站是:http://www.ashleyit.com/rs/main.htm,是一個針對XMLHttpRequest的瘦包裝器。

    ·一個簡單的組件,作為Brent Ashley的更全面的遠程腳本工作(參見Javascript遠程腳本-JSRS在多語言服務器端)的一部分發行。

    2.8 Sack(在開發中,自從2005年5月)

    網站是:http://twilightuniverse.com/2005/05/sack-of-ajax/,是一個針對XMLHttpRequest的瘦包裝器。

    ·調用者能指定回叫函數或者回叫DOM對象。借助于回叫DOM,應答文本直接被推入到DOM中

    2.9 Sarissa(發行于2月,2003年)

    網站是:http://sarissa.sf.net,是一種Javascript API,它封裝了在瀏覽器端可以獨立調用XML的功能。

    ·可移植的XMLHttpRequest創建

    ·可移植的XPath查詢

    ·可移植的DOM操作

    ·可移植的XSLT

    ·可移植的XML串行化

    ·開源(GPL2.0和LGPL2.1)。來自多方面貢獻者。

    2.10 XHConn(發行于自從4月,2005年)

    網站是:http://xkr.us/code/javascript/XHConn/,是一個對XMLHttpRequest的瘦包裝器。

    ·例如:

    new XHConn().connect("mypage.php","POST","foo=bar&baz=qux",fnWhenDone);

    ·開源許可。由Brad Fults所維護。

    服務器端:多種語言

    3.1 跨平臺異步的接口工具箱(5月2005年)

    CPAINT:http://cpaint.sourceforge.net/,是一真正的支持PHP和ASP/Vbscript的Ajax實現和JSRS(JavaScript遠程腳本)實現。CPAINT提供給你需求的代碼在后臺實現AJAX和JSRS,而返回的數據以JavaScript形式在前臺操作,格式化和顯示。這允許你創建能提供接近實時的反饋給用戶的web應用程序。

    ·支持PHP&ASP

    ·針對所有函數的一致的JavaScript文件

    ·支持遠程腳本和XML

    ·支持本地和遠程函數

    ·單個或者多個XMLHTTP對象

    ·以文本或者JavaScript XML/DOM文檔對象方式返回后臺數據

    ·能支持POST和GET請求

    ·后臺代理函數來訪問遠程函數和數據

    ·在所有的主要瀏覽器上測試過

    ·在GNU GPL&LGPL保護下發行

    3.2 SAJAX(可用,但是不是1.0版本;自從3月2005年)

    網站是:http://www.modernmethod.com/sajax/,直接把調用從Javascript發送到你的服務器端語言并再次回返。例如,調用一個javascript方法x_calculateBudget(),將先到達服務器和調用一個Java calculateBudget()方法,然后以javascript方式把值返回到x_calculateBudget_cb()。

    ·便利從Javascript代理函數到后臺操作的映射。

    ·能夠代理對眾多服務器端平臺(ASP/ColdFusion/Io/Lua/Perl/PHP/Python/Ruby)的調用。

    ·開源許可。來自多方面貢獻者。

    3.3 Javascipt對象標志(JSON)和JSON-RPC

    JSON(http://www.crockford.com/JSON/index.html),是一個"胖的自由的XML選擇",而JSON-RPC(http://www.json-rpc.org/)是一種遠程過程協議,類似于XML-RPC,強有力支持Javascript客戶。

    ·實現多服務器端平臺(http://www.json-rpc.org/impl.xhtml):Java,Python,Ruby,Perl。

    ·針對每種平臺有獨立的打包和許可,如JSON-RPC-Java(http://oss.metaparadigm.com/jsonrpc/)。

    3.4 Javascript遠程腳本(JSRS)(自從2000年)

    網址是:http://www.ashleyit.com/rs/jsrs/test.htm,直接把調用從Javascript發送到你的服務器端語言并再次回返。

    ·知名的瀏覽器:IE4+,NS4.x,NS6.x,Mozilla,Opera7和Galeon。

    ·服務器端支持:ASP,ColdFusion,PerlCGI,PHP,Python和JSP(servlet)。

    ·開源許可。由Brent Ashley(http://www.ashleyit.com/)提供支持。

    4 服務器端:Java

    注意:許多現有的框架最近正在添加Java支持(例如struts),我將在后面指出。

    4.1 WebORB for Java(自從2005年8月)

    網址:http://www.themidnightcoders.com/weborb/aboutWeborb.htm,是一個平臺,支持開發AJAX和基于Flash的胖客戶端應用程序,并可以把它們與Java對象和XML Web服務相系起來。在線舉例(http://www.themidnightcoders.com/examples)

    ·WebORB包括一個稱作豐富的客戶系統(http://www.themidnightcoders.com/rcs/index.htm)的客戶端庫。該豐富的客戶系統提供一簡單的在線api來綁定到并調用任何Java對象,XML Web服務或者EJB上的方法。

    ·支持同步的和異步的方法調用。

    ·并不要求在服務器端代碼上作任何修改,不需要定制方法屬性,特別的簽名或者參數類型。★不要求設計時生成代理。

    ·同步調用返回來自于該調用(不需要回叫)的數據。異步的調用依賴于一個回叫實現。

    ·任何服務器端方法能被同步地或者異步地調用。

    ·客戶應用程序能向服務器對象請求指定的活動方式。結果,對象能被輕易地創建而不需任何特殊的編程

    ·提供一個特定API來處理數據庫查詢結果-服務器代碼能返回Data集合或者Data表,而客戶端以一個特殊RecordSet JavaScript對象來顯示這個結果。該對象提供一個方法以檢索列名和行數據。

    ·支持數據分頁技術。客戶應用程序能檢索頁面中的數據。

    ·支持所有的服務器端參數類型并返回值-原型,字符串,復合類型,數組,本機.net集合,遠程參考。

    ·共有兩種版本可用:標準版(自由)和專業版(商業許可)

    4.2 Echo 2(自從3月2005年)

    網址是:http://www.nextapp.com/products/echo2/,允許你用純Java代碼編寫Ajax應用軟件(范例(http://demo.nextapp.com/InteractiveTest/ia))。

    自動地生成HTML和Javascript。

    ·協調瀏覽器和服務器之間的消息。消息形式為XML。

    ·如果需要,可以手工編寫定制的Javascript部件。

    ·開源許可(Mozilla公共許可或者GNU LGPL)。源于Next App,Inc.(http://www.nextapp.com/)。

    4.3 Direct Web Remoting (DWR)(2005年)

    網址是:http://www.getahead.ltd.uk/dwr/,是一個框架,用于直接從Javascript代碼中調用Java方法。

    ·象SAJAX,能把Javascript中的調用傳遞到Java方法,并返回到Javascript回叫。

    ·能與任何web框架(Struts,Tapestry,等等)一起使用。

    ·開源許可(Apache(http://www.apache.org/LICENSE.txt))。由Joe Walker(http://www.getahead.ltd.uk/sg/space/joe/)所支持。被加入到WebWork(http://www.opensymphony.com/webwork/)版本。

    4.4 SWATO(2005年)

    網址是:http://swato.dev.java.net/,是一套可重用的和良好集成的Java/JavaScript庫,它實現了一種更容易的方式來改變你的web應用程序的交互,它是通過AJAX方式實現。

    ·服務器端Java庫能被容易地配置到所有的Servlet 2.3+匹配的容器中。

    ·客戶端JavaScript庫能工作在支持HttpXMLRequest的各種瀏覽器中。

    ·使用JSON來在服務器端編組你的POJO數據。這樣你能存取在任何JavaScript環境(HTML,XUL,SVG)中的遠程數據,這種存取可以容易地通過硬編碼或者與某種成熟的JavaScript庫集成來實現。

    ·提供一個簡單的接口來使你的JavaScript代碼可以與暴露在客戶端的遠程POJO交互(RPC等)。

    ·使用web.xml中的<servlet>和<filter>的容易且靈活的配置,并能(但不是依賴)與Spring集成到一起。

    ·提供了幾個可幫助你快速開發web應用程序的組件(如自動完成的文本框,在線表單,在線列表,等等)。

    5 服務器端:Lisp

    5.1 CL-Ajax

    網址:http://cliki.net/cl-ajax,實現Javascript直接調用服務器端Lisp函數。

    ·如下輸出函數:

    (export-函數 #’my-函數)

    ·可以產生帶有參數的Javascript代理。

    ·能回叫Javascript函數或者DOM對象。

    ·可以被集成進SAJAX。

    ·開源(定制,非常靈活,許可)。由[Richard Newman](http://www.holygoat.co.uk/)所維護。

    6 服務器端:.NET

    6.1 WebORB for.NET(自從8月2005年)

    網址:http://www.themidnightcoders.com/weborb/aboutWeborb.htm,是一個平臺,用于開發AJAX和基于Flash的胖客戶端應用程序,并能把它們連接到.NET對象和XML Web服務。(在線舉例(http://www.themidnightcoders.com/examples))

    ·WebORB包括一個客戶端庫,名叫Rich Client System(http://www.themidnightcoders.com/rcs/index.htm)。Rich Client System提供一簡單的在線api以綁定到和調用任何.NET對象或者XML Web服務上的任何方法。

    ·支持同步和異步的方法調用

    ·并不要求在服務器端代碼上作任何修改,不需要定制方法屬性,特別的簽名或者參數類型。**不要求設計時代理生成。

    ·同步調用返回來自于該調用的數據(不需要回叫)。異步的調用依賴于一個回叫實現。

    ·任何服務器端方法能被同步地或者異步地調用。

    ·客戶應用程序能向服務器對象請求指定的活動方式。結果,對象能被輕易地創建而不需任何特殊的編程

    ·提供一個特定API來處理數據庫查詢結果-服務器代碼能返回DataSet或者DataTable,而客戶端以一個特殊RecordSet JavaScript對象來顯示這個結果。該對象提供一個方法以檢索列名和行數據

    ·支持數據頁面技術。客戶端應用程序能檢索頁面中的數據。

    ·支持所有的服務器端參數類型并返回值-原型,字符串,復合類型,數組,本機.net集合,遠程參考

    ·共有兩種版本可用的:標準版(自由)和專業版(商業許可)

    6.2 Ajax.NET(自從3月2005年)

    網址是:http://ajax.schwarz-interactive.de/,是一個庫,實現從Javascript到服務器端.NET的存取。

    ·象SAJAX,能把Javascript中的調用傳遞到.NET方法,并返回到Javascript回叫。

    ·能存取來自于JavaScript的會話數據。

    ·緩存結果

    ·自由使用,可用的源碼,未指定使用許可。由Michael Schwarz(http://weblogs.asp.net/mschwarz/)所維護。

    ·不允許改變源代碼,用屬性標記方法

    ·完整的類支持以返回客戶端JavaScript值

    ·使用HtmlControls來進行輸入和返回值

    ·可以返回數據表,數據集,數據視圖,數組和集合

    7 服務器端:PHP

    7.1 AjaxAC(自從2005年4月)

    網址是:http://ajax.zervaas.com.au/,用單個的PHP類封裝了完整的應用程序。

    ·所有的應用程序代碼是自包含在單個類中(附加另外一些JavaScript庫)

    ·干凈利索地調用PHP文件/HTML頁面。只需創建應用程序類,然后參照應用程序JavaScript和依附任何需要的HTML元素到該應用程序。

    ·容易地處理JavaScript事件的內嵌功能

    ·創建子需要并處理它們的內嵌功能

    ·允許定制的配置值,因此某些單元能在運行時間設置

    ·無凌亂的JavaScript代碼夾雜在調用HTML的代碼中-所有的事件是被動態依附的

    ·由于以上兩個原因容易和模板引擎集成到一起

    ·容易鉤到(hook in to)已有的PHP類或者MySQL數據庫以返回來自于子需求的數據

    ·能夠容易地進一步生成JavaScript對象的可擴展的窗口小組件結構(但是還需要做一些工作)

    背景:

    ·開源許可(Apache2.0)。由Zervaas Enterprises(http://ajax.zervaas.com.au/)支持

    7.2 JPSpan

    網址是:http://jpspan.sourceforge.net/wiki/doku.php,直接把Javascript調用傳遞到PHP函數。

    ·進行了嚴肅的單元測試。

    ·開源許可(PHP)。

    7.3 XAJAX

    網址是:http://xajax.sf.net,直接把Javascript調用傳遞到PHP函數。

    ·使用Javascript代理來調用PHP腳本。

    ·開源。由J.Max Wilson所創。

    8 服務器端:Ruby

    Ruby On Rails(http://www.rubyonrails.org/)是一個通常的強力支持Ajax的web框架:

    ·當Ajax出現的時候Rails還處于其發展的早期,因此Ajax可能逐漸成為Rails框架的核心。

    ·生成瀏覽器中大多數/全部的窗口小組件和動畫的Javascript腳本。

    ·支持服務器端調用。

    ·調度支持。

    ·開源許可。



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=542157

    posted @ 2005-12-05 13:19 只牽這只狗 閱讀(229) | 評論 (0)編輯 收藏

    僅列出標題
    共3頁: 上一頁 1 2 3 下一頁 
    主站蜘蛛池模板: 亚洲精品一卡2卡3卡四卡乱码| 91在线精品亚洲一区二区| 亚洲欧洲日产国码av系列天堂| 国产亚洲综合成人91精品| 午夜亚洲www湿好大| 亚洲免费福利视频| 久久久久亚洲AV无码去区首| 成人嫩草影院免费观看| 久久精品视频免费| 人成午夜免费视频在线观看| 四虎永久成人免费| 精品亚洲永久免费精品| 亚洲午夜久久久精品电影院| 日韩亚洲翔田千里在线| 男女一边桶一边摸一边脱视频免费 | 亚洲黄色免费观看| 亚洲人成色777777精品| xxxxx做受大片视频免费| 91香焦国产线观看看免费| 日韩精品视频免费网址| 亚洲永久精品ww47| 亚洲mv国产精品mv日本mv| 日本特黄特色AAA大片免费| 99热免费在线观看| 国产午夜免费秋霞影院| 久久久久久亚洲av成人无码国产| 午夜在线a亚洲v天堂网2019| 国产99久久久久久免费看| 亚洲精品免费网站| 亚洲第一页综合图片自拍| 亚洲美女大bbbbbbbbb| 日韩久久无码免费毛片软件| 免费观看美女用震蛋喷水的视频 | 国产精品成人免费综合| 久久精品国产亚洲香蕉| 亚洲av成人中文无码专区| 久久永久免费人妻精品| 免费A级毛片无码久久版| 亚洲经典在线中文字幕| 添bbb免费观看高清视频| **一级一级毛片免费观看|