posts - 40,  comments - 7,  trackbacks - 0
            2006年8月18日
          關(guān)于inode;


          inode 譯成中文就是索引節(jié)點(diǎn)。每個(gè)存儲(chǔ)設(shè)備或存儲(chǔ)設(shè)備的分區(qū)(存儲(chǔ)設(shè)備是硬盤、軟盤、U盤 ... ... )被格式化為文件系統(tǒng)后,應(yīng)該有兩部份,一部份是inode,另一部份是Block,Block是用來存儲(chǔ)數(shù)據(jù)用的。而inode呢,就是用來存儲(chǔ)這些數(shù)據(jù)的信息,這些信息包括文件大小、屬主、歸屬的用戶組、讀寫權(quán)限等。inode為每個(gè)文件進(jìn)行信息索引,所以就有了inode的數(shù)值。操作系統(tǒng)根據(jù)指令,能通過inode值最快的找到相對(duì)應(yīng)的文件。

          做個(gè)比喻,比如一本書,存儲(chǔ)設(shè)備或分區(qū)就相當(dāng)于這本書,Block相當(dāng)于書中的每一頁,inode 就相當(dāng)于這本書前面的目錄,一本書有很多的內(nèi)容,如果想查找某部份的內(nèi)容,我們可以先查目錄,通過目錄能最快的找到我們想要看的內(nèi)容。雖然不太恰當(dāng),但還是比較形象。

          當(dāng)我們用ls 查看某個(gè)目錄或文件時(shí),如果加上-i 參數(shù),就可以看到inode節(jié)點(diǎn)了;比如我們前面所說的例子;



          [root@localhost ~]# ls -li lsfile.sh
          2408949 -rwxr-xr-x 1 root root 7 04-21 12:47 lsfile.sh

          lsfile.sh 的inode值是 2408949 ; 查看一個(gè)文件或目錄的inode,要通過ls 命令的的 -i參數(shù)。


          2.10 inode 相同的文件是硬鏈接文件;


          在Linux 文件系統(tǒng)中,inode值相同的文件是硬鏈接文件,也就是說,不同的文件名,inode可能是相同的,一個(gè)inode值可以對(duì)應(yīng)多個(gè)文件。理解鏈接文件并不難,看看例子就會(huì)了。在Linux中,鏈接文件是通過ln工具來創(chuàng)建的。


          2.11 創(chuàng)建硬鏈接,硬鏈接和源文件關(guān)系;


          用ln 創(chuàng)建文件硬鏈接的語法:



          # ln 源文件 目標(biāo)文件

          下面我們舉一個(gè)例子,在這個(gè)例子中,我們要為sun.txt 創(chuàng)建其硬鏈接sun002.txt。然后看一下sun.txt和sun002.txt的屬性的變化;


          [root@localhost ~]# ls -li sun.txt 注:查看sun.txt的屬性;
          2408263 -rw-r--r-- 1 root root 29 04-22 21:02 sun.txt 注:這是sun.txt的屬性;
          [root@localhost ~]# ln sun.txt sun002.txt 注:我們通過ln 來創(chuàng)建sun.txt的硬鏈接文件sun002.txt
          [root@localhost ~]# ls -li sun* 注:我們列一下sun.txt 和sun002.txt
          2408263 -rw-r--r-- 2 root root 29 04-22 21:02 sun002.txt
          2408263 -rw-r--r-- 2 root root 29 04-22 21:02 sun.txt

          我們可以看到sun.txt在沒有創(chuàng)建硬鏈接文件sun002.txt的時(shí)候,其鏈接個(gè)數(shù)是1(也就是-rw-r--r--后的那個(gè)數(shù)值),創(chuàng)建了硬鏈接sun002.txt創(chuàng)建后,這個(gè)值變成了2。也就是說,我們每次為sun.txt創(chuàng)建一個(gè)新的硬鏈接文件后,其硬鏈接個(gè)數(shù)都會(huì)增加1。

          inode值相同的文件,他們的關(guān)系是互為硬鏈接的關(guān)系。當(dāng)我們修改其中一個(gè)文件的內(nèi)容時(shí),互為硬鏈接的文件的內(nèi)容也會(huì)跟著變化。如果我們刪除互為硬鏈接關(guān)系的某個(gè)文件時(shí),其它的文件并不受影響。比如我們把sun.txt刪除后,我們還是一樣能看到sun002.txt的內(nèi)容,并且sun02.txt仍是存在的。

          可以這么理解,互為硬鏈接關(guān)系的文件,他們好象是克隆體,他們的屬性幾乎是完全一樣;

          下面的例子,我們把sun.txt刪除,然后我們看一下sun002.txt 是不是能看到其內(nèi)容。



          [root@localhost ~]# rm -rf sun.txt
          [root@localhost ~]# more sun002.txt

          注意:硬鏈接不能為目錄創(chuàng)建,只有文件才能創(chuàng)建硬鏈接。


          2.12 軟鏈接的創(chuàng)建,及軟接與源文件的關(guān)系;


          創(chuàng)建軟鏈接(也被稱為符號(hào)鏈接)的語法;



          # ln -s 源文文件或目錄 目標(biāo)文件或目錄

          軟鏈接也叫符號(hào)鏈接,他和硬鏈接有所不同,軟鏈接文件只是其源文件的一個(gè)標(biāo)記。當(dāng)我們刪除了源文件后,鏈接文件不能獨(dú)立存在,雖然仍保留文件名,但我們卻不能查看軟鏈接文件的內(nèi)容了。



          [root@localhost ~]# ls -li linuxsir001.txt
          2408274 -rw-r--r-- 1 root root 29 04-22 21:53 linuxsir001.txt
          [root@localhost ~]# ln -s linuxsir001.txt linuxsir002.txt
          [root@localhost ~]# ls -li linuxsir001.txt linuxsir002.txt
          2408274 -rw-r--r-- 1 root root 29 04-22 21:53 linuxsir001.txt
          2408795 lrwxrwxrwx 1 root root 15 04-22 21:54 linuxsir002.txt -> linuxsir001.txt

          解釋

          上面的例子,首先我們查看 linuxsir001.txt 的屬性,比如inode 、所屬文件種類、創(chuàng)建或修改時(shí)間等... ...我們來對(duì)比一下:

          首先 對(duì)比一下節(jié)點(diǎn):兩個(gè)文件的節(jié)點(diǎn)不同;
          其次 兩個(gè)文件的歸屬的種類不同 linuxsir001.txt是-,也就是普通文件,而linuxsir002.txt 是l,它是一個(gè)鏈接文件;
          第三 兩個(gè)文件的讀寫權(quán)限不同 linuxsir001.txt 是rw-r--r-- ,而linuxsir002.txt的讀寫權(quán)限是 rwxrwxrwx
          第三 兩者的硬鏈接個(gè)數(shù)相同;都是1
          第四 兩文件的屬主和所歸屬的用戶組相同;
          第五 修改(或訪問、創(chuàng)建)時(shí)間不同;

          我們還注意到了linuxsir002.txt 后面有一個(gè)標(biāo)記 ->,這表示linuxsir002.txt 是linuxsir001.txt的軟鏈接文件。

          值得我們注意的是:當(dāng)我們修改鏈接文件的內(nèi)容時(shí),就意味著我們在修改源文件的內(nèi)容。當(dāng)然源文件的屬性也會(huì)發(fā)生改變,鏈接文件的屬性并不會(huì)發(fā)生變化。當(dāng)我們把源文件刪除后,鏈接文件只存在一個(gè)文件名,因?yàn)槭チ嗽次募攒涙溄游募簿筒淮嬖诹恕_@一點(diǎn)和硬鏈接是不同的;



          [root@localhost ~]# rm -rf linuxsir001.txt 注:刪除linuxsir001.txt
          [root@localhost ~]# ls -li linuxsir002.txt 注:查看linuxsir002 的屬性;
          2408795 lrwxrwxrwx 1 root root 15 04-22 21:54 linuxsir002.txt -> linuxsir001.txt
          [root@localhost ~]# more linuxsir002.txt 注:查看linuxsir002.txt的內(nèi)容;
          linuxsir002.txt: 沒有那個(gè)文件或目錄 注:得到提示,linuxsir002.txt不存在。

          上面的例子告訴我們,如果一個(gè)鏈接文件失去了源,就意味著他已經(jīng)不存在了;

          我們可以看到軟鏈接文件,其實(shí)只是源文件的一個(gè)標(biāo)記,當(dāng)源文件失去時(shí),他也就是存在了。軟鏈接文件只是占用了inode來存儲(chǔ)軟鏈接文件屬性等信息,但文件存儲(chǔ)是指向源文件的。

          軟件鏈接,可以為文件或目錄都適用。無論是軟鏈接還是硬鏈接,都可以用rm來刪除。rm工具是通用的。
          參考資料:http://techcenter.dicder.com/2006/0908/content_185.htm
          posted @ 2007-07-13 09:54 Lansing 閱讀(755) | 評(píng)論 (0)編輯 收藏
          寫一些關(guān)于PL/SQL的語法,免得等到用到的時(shí)候還要去亂翻。
          1。控制流程(if,while)
          2。循環(huán)(for)
          3。游標(biāo)(cursor)
          4。異常處理(exception)

          1。控制流程()


          A.條件語句
          IF <statement> THEN
          ?? PL/SQL
          END IF;

          IF <statement> THEN
          ?? PL/SQL
          ELSE
          ?? PL/SQL
          END IF;

          IF
          <statement> THEN
          ?? PL/SQL
          ELSIF <statement> THEN
          ?? PL/SQL
          END IF;


          2。循環(huán)

          A.simple loop
          LOOP
          ?? SQL
          ?? EXIT WHEN <statement>;
          END LOOP;

          LOOP
          ?? SQL
          ?? IF
          <statement> THEN
          ?? EXIT;
          ?? END IF;
          END LOOP;

          B.While loop
          WHILE <statement> LOOP
          ?? SQL
          END LOOP;

          C.For loop
          FOR $counter in $low .. $high LOOP
          ?? SQL
          END LOOP


          3。游標(biāo)

          在PL/SQL程序中定義的游標(biāo)叫做顯式游標(biāo)。

          A.顯式游標(biāo)的處理由四個(gè)部分組成:
          cursor $cursorname is $Query;   --定義游標(biāo)
          open $cursorname;         --打開游標(biāo)
          fetch $cursorname into $othervariable  --把游標(biāo)中的東西取出
          close $cursorname??? --關(guān)閉游標(biāo)

          B.游標(biāo)屬性
          %found?? ?? ?? 布爾型屬性,當(dāng)最近一次讀紀(jì)錄成功
          時(shí) ,為true.
          %nofound                失敗時(shí),為false.
          %isopen
          %rowcount?? ?? 返回已從游標(biāo)中讀取的記錄數(shù)。

          C.參數(shù)化游標(biāo)

          所有的SQL語句在上下文區(qū)內(nèi)部都是可執(zhí)行的,因此都有一個(gè)游標(biāo)指向上下文區(qū),此游標(biāo)就是所謂的SQL游標(biāo)。
          與顯式游標(biāo)不同,SQL游標(biāo)不被程序打開和關(guān)閉。


          4.異常處理概念

          異常處理是用來處理正常執(zhí)行過程中未預(yù)料的事件。如果PL/SQL程序塊一旦產(chǎn)生異常而又沒有指出如何處理時(shí),程序會(huì)自動(dòng)終止。
          異常處理部分放在PL/SQL的后半部分,結(jié)構(gòu)為:

          EXCEPTION
          ?????? WHEN first_exception THEN <code to handle first exception>
          ?????? WHEN second_exception THEN <code to handle second exception>
          ?????? WHEN OTHERS THEN <
          code to handle second exception >? --OTHERS必須放在最后

          異常分為預(yù)定義和用戶定義兩種。
          用戶定義的異常是通過顯式使用RAISE語句來引發(fā)。如

          DECLARE
          ? e_TooManyStudents EXCEPTION;? -- 類型為Exception,用于指示錯(cuò)誤條件
          ? v_CurrentStudents NUMBER(3);? -- HIS-101學(xué)生注冊當(dāng)前號(hào)
          ? v_MaxStudents NUMBER(3);????? -- HIS-101學(xué)生注冊允許的最大號(hào)

          BEGIN
           /* 找出注冊學(xué)生當(dāng)前號(hào)和允許的最大號(hào) */

          ? SELECT current_students, max_students

          ??? INTO v_CurrentStudents, v_MaxStudents

          ??? FROM classes

          ??? WHERE department = 'HIS' AND course = 101;

          ? /* 檢查學(xué)生的號(hào) */

          ? IF v_CurrentStudents > v_MaxStudents THEN

          /* 太多的學(xué)生注冊,則觸發(fā)例外處理 */

          ? RAISE e_TooManyStudents;

          ? END IF;

          EXCEPTION

          ? WHEN e_TooManyStudents THEN

          ??? /* 當(dāng)太多的學(xué)生注冊,就插入信息解釋發(fā)生過錯(cuò)誤 */

          ??? INSERT INTO log_table (info) VALUES ('History 101 has ' || v_CurrentStudents ||

          ????? 'students: max allowed is ' || v_MaxStudents);

          END;


          END;

          用戶定義的的異常處理
          可以使用RAISE_APPLICATION_ERROR來創(chuàng)建自己的錯(cuò)誤處理:
          RAISE_APPLICATION_ERROR(error_number,error_message,[keep_errors]);
          其中
          error_number是從-20000到-20999之間的參數(shù); error_message是相應(yīng)的提示信息,小于512字節(jié)。如:

          CREATE OR REPLACE PROCEDURE Register (
          p_StudentID IN students.id%TYPE,
          p_Department IN classes.department%TYPE,
          p_Course IN classes.course%TYPE) AS
          v_CurrentStudents NUMBER;? -- 班上學(xué)生的當(dāng)前號(hào)
          v_MaxStudents NUMBER;????? -- 班上學(xué)生的最大號(hào)

          BEGIN
          /* 找出學(xué)生的當(dāng)前號(hào)和最大號(hào) */
          SELECT current_students, max_students
          ?INTO v_CurrentStudents, v_MaxStudents
          FROM classes
          WHERE course = p_Course
          AND department = p_Department;

          /* 確認(rèn)另外的學(xué)生是否有足夠的教室 */
          IF v_CurrentStudents + 1 > v_MaxStudents THEN
          RAISE_APPLICATION_ERROR(-20000, 'Can''t add more students to ' ||
          p_Department || ' ' || p_Course);
          END IF;

          /* 加一個(gè)學(xué)生在本班 */
          ClassPackage.AddStudent(p_StudentID, p_Department, p_Course);

          EXCEPTION
          WHEN NO_DATA_FOUND THEN
             
          RAISE_APPLICATION_ERROR(-20001, p_Department || ' ' || p_Course ||
          ??? ?? ??
          ' doesn''t exist!');
          END Register;

          posted @ 2007-01-23 10:10 Lansing 閱讀(378) | 評(píng)論 (0)編輯 收藏
          關(guān)于ODBC數(shù)據(jù)源連接文本?

          ????????????  在《外部數(shù)據(jù)庫的連接原理》一講中我們說過,ODBC提供對(duì)多種數(shù)據(jù)庫的支持,如dBase、Access、MS?SQL?
          ????????????Server及Oracle,也就是說運(yùn)用ODBC數(shù)據(jù)源中所提供的連接代碼,我們可以實(shí)現(xiàn)對(duì)多種數(shù)據(jù)庫的連接。以連接Access數(shù)據(jù)庫為例,ODBC數(shù)據(jù)源連接文本的格式是:
          ????????????  “Driver={數(shù)據(jù)庫驅(qū)動(dòng)程序};Dbq=數(shù)據(jù)庫文件;”
          ????????????  在以上連接文本中,如果數(shù)據(jù)庫跟程序在同一目錄下,或者用變量DefaultDir指定了數(shù)據(jù)庫所在目錄,則數(shù)據(jù)庫文件可以不用全路徑名,如下即可:
          ????????????  “ODBC;DBQ=MSAccess.mdb;Driver={Microsoft?Access?Driver?(*.mdb)};”
          ????????????  如下也可:
          ????????????  “ODBC;DBQ=MSAccess.mdb;DefaultDir=d:\Downloads\e21;Driver={Microsoft?
          ????????????Access?Driver?(*.mdb)};”
          ????????????  如果數(shù)據(jù)庫跟程序不在同一目錄下,或者沒有用變量DefaultDir指定數(shù)據(jù)庫所在目錄,則數(shù)據(jù)庫文件需要用全路徑名,如下:
          ????????????  “ODBC;DBQ=E:\Quake?III?Arena\MSAccess.mdb;Driver={Microsoft?Access?
          ????????????Driver?(*.mdb)};”
          ????????????  以上所說的是連接Access數(shù)據(jù)庫的格式,那么連接其他數(shù)據(jù)庫的ODBC數(shù)據(jù)源連接文本又是怎樣的?連接不同類型的數(shù)據(jù)庫要使用不同的對(duì)應(yīng)驅(qū)動(dòng)程序,沒忘記吧!不同的驅(qū)動(dòng)程序當(dāng)然它們的參數(shù)組合也就不同了,每一種不同驅(qū)動(dòng)程序都有其特定的的參數(shù)形式:?

          ????????????  ⑴、MS?Access?ODBC?DSNless?連接:
          ????????????  ☆、參數(shù):Driver?設(shè)置值:{Microsoft?Access?Driver?(*.mdb)}
          ????????????  ☆、參數(shù):Dbq?設(shè)置值:實(shí)際路徑文件名稱
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?Access?Driver?
          ????????????(*.mdb)};Dbq=c:\somepath\dbname.mdb;Uid=Admin;Pwd=pass;?”
          ????????????  ⑵、dBase?ODBC?DSNless?連接:?
          ????????????  ☆、參數(shù):Driver?設(shè)置值:{Microsoft?dBASE?Driver?(*.dbf)}
          ????????????  ☆、參數(shù):Dbq?設(shè)置值:實(shí)際路徑文件名稱
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?dBASE?Driver?
          ????????????(*.dbf)};DriverID=277;Dbq=c:\somepath\dbname.dbf;?”
          ????????????  ⑶、Oracle?ODBC?DSNless?連接:
          ????????????  ☆、參數(shù):Driver?設(shè)置值:{Microsoft?ODBC?for?Oracle}
          ????????????  ☆、參數(shù):Dbq?設(shè)置值:實(shí)際路徑文件名稱
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?ODBC?for?
          ????????????Oracle};Server=OracleServer.world;Uid=admin;Pwd=pass;?”
          ????????????  ⑷、MS?SQL?Server?DSNless?連接:?
          ????????????  ☆、參數(shù):Driver?設(shè)置值:{SQL?Server};
          ????????????  ☆、參數(shù):Server?設(shè)置值:服務(wù)器名稱
          ????????????  ☆、參數(shù):Database?設(shè)置值:數(shù)據(jù)表名稱
          ????????????  ☆、參數(shù):Uid?設(shè)置值:用戶名稱
          ????????????  ☆、參數(shù):Pwd?設(shè)置值:密碼
          ????????????  ☆、例句:
          ????????????  “Driver={SQL?
          ????????????Server};Server=servername;Database=dbname;Uid=sa;Pwd=pass;?”
          ????????????  ⑸、MS?Text?Driver?DSNless?連接:?
          ????????????  ☆、參數(shù):Driver?設(shè)置值:{Microsoft?Text?Driver?(*.txt;?*.csv)}
          ????????????  ☆、參數(shù):Dbq?設(shè)置值:實(shí)際路徑文件名稱
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?Text?Driver?(*.txt;?
          ????????????*.csv)};Dbq=c:\somepath\;Extensions=asc,csv,tab,txt;Persist?Security?
          ????????????Info=False;?”
          ????????????  ⑹、Visual?Foxpro?DSNless?連接:
          ????????????  ☆、參數(shù):Driver?設(shè)置值:{Microsoft?Visual?FoxPro?Driver}
          ????????????  ☆、參數(shù):SourceType?設(shè)置值:DBC
          ????????????  ☆、參數(shù):SourceDB?設(shè)置值:實(shí)際路徑文件名稱?
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?Visual?FoxPro?
          ????????????Driver};SourceType=DBC;SourceDB=c:\somepath\dbname.dbc;Exclusive=No;”?

          ????????????  ⑺、MySQL?DSNless?連接:
          ????????????  ☆、參數(shù):Driver?設(shè)置值:{mysql}
          ????????????  ☆、參數(shù):database?設(shè)置值:數(shù)據(jù)表名稱
          ????????????  ☆、參數(shù):uid?設(shè)置值:用戶名稱
          ????????????  ☆、參數(shù):pwd?設(shè)置值:密碼
          ????????????  ☆、例句:?
          ????????????  “driver={mysql};?
          ????????????database=yourdatabase;uid=username;pwd=password;option=16386”
          ????????????*******************************************************************
          ????????????SQL語言簡介?

          ????????????  在上一講中我們介紹了連接外部數(shù)據(jù)庫的方法,那么連接之后怎樣對(duì)外部數(shù)據(jù)庫進(jìn)行讀取、顯示、增刪、更新、查詢等操作呢?這些操作需要通過外部數(shù)據(jù)庫等對(duì)象調(diào)用SQL指令才能完成。
          ????????????  ㈠、什么是SQL語言
          ????????????  SQL(Structure?Query?Languge,結(jié)構(gòu)化查詢語言)是一種數(shù)據(jù)庫專用的計(jì)算機(jī)語言,不管是Oracle、MS?
          ????????????SQL?
          ????????????、Access、MySQL或其他公司的數(shù)據(jù)庫,也不管數(shù)據(jù)庫建立在大型主機(jī)或個(gè)人計(jì)算機(jī)上,都可以使用SQL語言來訪問和修改數(shù)據(jù)庫的內(nèi)容。雖然不同公司的數(shù)據(jù)庫軟件多多少少會(huì)增加一些專屬的SQL語法,但大體上,它們還是遵循ASNI(美國國家標(biāo)準(zhǔn)協(xié)會(huì))制定的SQL標(biāo)準(zhǔn)。因?yàn)镾QL語言具有易學(xué)習(xí)及閱讀等特性,所以SQL逐漸被各種數(shù)據(jù)庫廠商采用,而成為一種共通的標(biāo)準(zhǔn)查詢語言。只要你學(xué)會(huì)SQL,即可操作各種數(shù)據(jù)庫如Visual?
          ????????????Foxpro、Access、dBase等等。總之,SQL語言是各種數(shù)據(jù)庫都可以使用的數(shù)據(jù)庫查詢語言。
          ????????????  SQL語言不僅僅具有查詢數(shù)據(jù)庫的功能,而且可以對(duì)數(shù)據(jù)庫完成選取、增刪、更新與跳轉(zhuǎn)等各種操作。
          ????????????  ㈡、SQL語言的組成
          ????????????  SQL語言是由命令(函數(shù))、子句、運(yùn)算符、加總函數(shù)及通配符等組成,分述如下:
          ????????????  1、命令
          ????????????  SQL的命令可分成數(shù)據(jù)定義語言與數(shù)據(jù)操作語言,數(shù)據(jù)定義語言可用來建立新的數(shù)據(jù)庫、數(shù)據(jù)表、字段及索引等,本教程不予介紹;另一為數(shù)據(jù)操作語言,可用來建立查詢表、排序、篩選數(shù)據(jù)、修改、增刪等動(dòng)作。數(shù)據(jù)定義語言命令常用的有選擇、添加、刪除和修改這四種:
          ????????????  ⑴、命令:SELECT
          ????????????  中文意思:選擇
          ????????????  說明:用于找出合乎條件的記錄
          ????????????  ⑵、命令:INSERT
          ????????????  中文意思:插入
          ????????????  說明:用于增加一筆記錄或合并兩個(gè)數(shù)據(jù)表
          ????????????  ⑶、命令:UPDATE
          ????????????  中文意思:更新
          ????????????  說明:用于更正合乎條件的記錄
          ????????????  ⑷、命令:DELETE
          ????????????  中文意思:刪除
          ????????????  說明:用于刪除合乎條件的記錄
          ????????????  2、子句
          ????????????  子句是用于設(shè)定命令要操作的對(duì)象(即參數(shù)),SQL所用的子句如下:
          ????????????  ⑴、子句:FROM?
          ????????????  中文意思:數(shù)據(jù)表
          ????????????  說明:用于指定數(shù)據(jù)表
          ????????????  ⑵、子句:WHERE
          ????????????  中文意思:條件
          ????????????  說明:用于設(shè)定條件
          ????????????  ⑶、GROUP?BY
          ????????????  中文意思:分組(合并)
          ????????????  說明:用于設(shè)定分組
          ????????????  ⑷、ORDER?BY
          ????????????  中文意思:排序
          ????????????  說明:用于設(shè)定輸出的順序及字段
          ????????????  3、運(yùn)算符
          ????????????  子句參數(shù)中的運(yùn)算符使子句構(gòu)成不同的語法格式,如“字段1='100'”、“字段1>'100'”等。運(yùn)算符又分邏輯運(yùn)算符與比較運(yùn)算符。
          ????????????  ◇邏輯運(yùn)算符如下:
          ????????????  ⑴、運(yùn)算符:AND
          ????????????  中文意思:并且
          ????????????  說明:邏輯且
          ????????????  ⑵、運(yùn)算符:OR?
          ????????????  中文意思:或者
          ????????????  說明:邏輯非
          ????????????  ⑶、運(yùn)算符:NOT
          ????????????  中文意思:取反
          ????????????  說明:邏輯非或邏輯反
          ????????????  ◇比較運(yùn)算符如下:
          ????????????  ⑴、運(yùn)算符:<?說明:小于
          ????????????  ⑵、運(yùn)算符:≤?說明:小于等于
          ????????????  ⑶、運(yùn)算符:≥?說明:大于等于
          ????????????  ⑷、運(yùn)算符:>?說明:大于
          ????????????  ⑸、運(yùn)算符:=?說明:等于
          ????????????  ⑹、運(yùn)算符:<>?說明:不等于
          ????????????  ⑺、運(yùn)算符:BETWEEN?說明:用于設(shè)定范圍?中文意思:在...之間
          ????????????  ⑻、運(yùn)算符:LIKE?說明:用于通配設(shè)定?中文意思:如同
          ????????????  ⑼、運(yùn)算符:IN?說明:用于集合設(shè)定?中文意思:在...之內(nèi)
          ????????????  4、加總函數(shù)
          ????????????  加總函數(shù)常常運(yùn)用在命令的參數(shù)中,如:“SELECT?SUM(數(shù)學(xué)),AVG(數(shù)學(xué))?FROM?成績單”。
          ????????????  ⑴、加總函數(shù):AVG?
          ????????????  中文意思:平均
          ????????????  說明:用于求指定條件的平均?
          ????????????  ⑵、加總函數(shù):COUNT
          ????????????  中文意思:數(shù)量
          ????????????  說明:用于求指定的數(shù)量
          ????????????  ⑶、加總函數(shù):SUM
          ????????????  中文意思:和
          ????????????  說明:用于求指定條件的和
          ????????????  ⑷、加總函數(shù):MAX
          ????????????  中文意思:最大值
          ????????????  說明:用于求指定條件的最大值
          ????????????  ⑸、加總函數(shù):MIN
          ????????????  中文意思:最小值
          ????????????  說明:用于求指定條件的最小值
          ????????????  5、通配符
          ????????????  ⑴、通配符:%?意義:任何長度的字符串(包括0)
          ????????????  ⑵、通配符:_?意義:下劃線表示任何一個(gè)字符
          ????????????  ⑶、通配符:[]?意義:中括號(hào)表示某個(gè)范圍內(nèi)的一個(gè)字符
          ????????????  在下一講將說明SQL語言是怎樣把命令(函數(shù))、子句、運(yùn)算符、及加總函數(shù)等組合在一起的。

          ????????????*************************************************************************

          ????????????嵌入式SQL的應(yīng)用?

          ????????????  SQL語句可以單獨(dú)在數(shù)據(jù)庫系統(tǒng)本身中執(zhí)行,但如果運(yùn)用在其他編程工具所編制的程序中,一般不能單獨(dú)執(zhí)行,而要把SQL語句嵌入到高級(jí)語言(如易語言)中使用,通過高級(jí)語言的命令和方法來調(diào)用之,此時(shí)SQL稱為嵌入式SQL。調(diào)用SQL語句的程序稱為宿主程序,在易語言中一般是把SQL語句作為宿主程序的唯一參數(shù)來直接處理。嵌入式SQL在使用上有一些規(guī)定,在易語言中目前的版本規(guī)定如下:
          ????????????  ⑴、在程序中要區(qū)分SQL語句和宿主語言的語句。在易語言中好區(qū)分,因?yàn)镾QL語句形式是英文的,而易語言是中文的,但在實(shí)際應(yīng)用時(shí)仍然有可能會(huì)混亂,所以易語言要把SQL語句轉(zhuǎn)化為文本型才能調(diào)用,即嵌入式SQL語句兩邊要用雙引號(hào)來標(biāo)示。
          ????????????  ⑵、允許SQL語句使用宿主程序的變量,但使用時(shí)要將宿主程序的變量跟外部數(shù)據(jù)庫中表格的字段名區(qū)別開來,區(qū)別方法如下:
          ????????????  ①、在易語言中要將變量類型轉(zhuǎn)化為文本型變量才能被SQL文本相加使用,比如下面的例子中有一個(gè)叫“數(shù)字1”的整數(shù)類型變量,插入到SQL文本中是這樣表達(dá):
          ????????????  外部數(shù)據(jù)庫1.查詢?(“select?*?from?chj?where?”?+?組合框1.內(nèi)容?+?“=”?+?到文本?(數(shù)字1))
          ????????????  ②、包含字段名的SQL文本兩邊加雙引號(hào),變量名不能在雙引號(hào)內(nèi),如上例。
          ????????????  ⑶、要將字段名跟字段值區(qū)別開來,區(qū)別方法如下:
          ????????????  ①、對(duì)于文本類型的字段,在其字段值兩邊要加上“'”號(hào)標(biāo)示其文本值,代表語法是:字段名稱=‘文本值’。如下:
          ????????????  外部數(shù)據(jù)庫1.查詢?(“select?*?from?chj?where?姓名='山大王'”)
          ????????????  又如下面“查找編輯框.內(nèi)容”中的字段值是文本型,嵌入式SQL語句如下:
          ????????????  外部數(shù)據(jù)庫1.查詢?(“select?*?from?chj?where?姓名==”?+?“'”?+?查找編輯框.內(nèi)容?+?
          “'”)
          ????????????  ②、對(duì)于數(shù)字類型的字段,在SQL語句中表示其字段值,兩邊不加符號(hào)標(biāo)示,代表語法是:字段名稱=數(shù)字值。如下兩例:
          ????????????  外部數(shù)據(jù)庫1.查詢?(“select?*?from?chj?where?”?+?組合框1.內(nèi)容?+?“=”?+?查找編輯框.內(nèi)容)?
          ????????????  外部數(shù)據(jù)庫1.查詢?(“select?*?from?chj?where?學(xué)號(hào)=17”)
          ????????????  ③、對(duì)于日期時(shí)間類型的字段,在其字段值兩邊要加上“#”號(hào)標(biāo)示其時(shí)間值,代表語法是:字段名稱=#時(shí)間值#。如下兩例:
          ????????????  外部數(shù)據(jù)庫1.查詢?(“select?*?from?chj?where?入學(xué)時(shí)間?BETWEEN?#2001-01-01#?and?
          ????????????#2002-01-01#”)
          ????????????  外部數(shù)據(jù)庫1.查詢?(“select?*?from?chj?where?”?+?組合框1.內(nèi)容?+?“=”?+?“#”?+?
          ????????????查找編輯框.內(nèi)容?+?“#”)
          ????????????  ④、也可以將SQL語句中的字段名(尤其是中文名)可用中括號(hào)括住,如:[字段名]。
          ????????????  
          ????????????  ⑷、SQL語句要用半角輸入法輸入,否則可能會(huì)出錯(cuò)。
          ????????????  那么在易語言中怎樣調(diào)用SQL語句呢?一般是在外部數(shù)據(jù)庫對(duì)象(控件)的方法中調(diào)用,試概括如下:
          ????????????  ⑴、對(duì)外部數(shù)據(jù)庫進(jìn)行查詢的方法。
          ????????????  對(duì)外部數(shù)據(jù)庫的查詢就是在對(duì)外部數(shù)據(jù)庫不加編輯改動(dòng)的前提下,只通過記錄集來對(duì)數(shù)據(jù)庫進(jìn)行顯示、查詢、篩選、排序和記錄集的合并等操作。
          ????????????  所有查詢類的方法起源于下面這個(gè)語句,其他查詢類語句是對(duì)這個(gè)語句的調(diào)用(將此語句作為唯一的參數(shù)),該語句如下:
          ????????????  外部數(shù)據(jù)庫.查詢?(查詢類SQL語句)
          ????????????  也可這樣表達(dá):
          ????????????  外部數(shù)據(jù)庫.查詢?(“SELECT...FROM...[WHERE]...[GROUP?BY]...[ORDER?BY]...?”)
          ????????????  該方法是對(duì)當(dāng)前被打開數(shù)據(jù)庫進(jìn)行數(shù)據(jù)查詢,返回的結(jié)果稱為“記錄集句柄”(即記錄集的標(biāo)記)。注意當(dāng)不再使用此記錄集時(shí),必須使用“關(guān)閉記錄集”將其關(guān)閉,如果失敗,返回0。在易語言中,將以上語句等同于記錄集句柄以作為其他查詢類語句的參數(shù)。為了使該參數(shù)在所有子程序中都能應(yīng)用,我們一般把它設(shè)置為整數(shù)型全局變量,并將其值設(shè)置如下:
          ????????????  記錄集句柄=外部數(shù)據(jù)庫.查詢?(查詢類SQL語句)
          ????????????  由于易語言要把SQL語句轉(zhuǎn)化為文本型才能調(diào)用,所以嵌入式SQL語句兩邊要有雙引號(hào),例句:
          ????????????  記錄集句柄?=?外部數(shù)據(jù)庫1.查詢?(“select?*?from?chj?”)
          ????????????  ※?“chj”是外部數(shù)據(jù)庫中一個(gè)表的名稱
          ????????????  又如,欲得到排序的記錄集,應(yīng)象下面這樣賦值:
          ????????????  記錄集句柄?=?外部數(shù)據(jù)庫1.查詢?(“SELECT?*?FROM?chj?ORDER?BY?語文?DESC”)
          ????????????  現(xiàn)將外部數(shù)據(jù)庫控件中其他的查詢類方法列舉如下:
          ????????????  ①、外部數(shù)據(jù)庫.重新查詢?(記錄集句柄)?即:
          ????????????  外部數(shù)據(jù)庫.重新查詢?(外部數(shù)據(jù)庫.查詢?(查詢類SQL語句))
          ????????????  例句:外部數(shù)據(jù)庫1.重新查詢?(外部數(shù)據(jù)庫1.查詢?(“select?*?from?chj?”))?
          ????????????  ②、外部數(shù)據(jù)庫.首記錄前?(記錄集句柄)?即:
          ????????????  外部數(shù)據(jù)庫.首記錄前?(外部數(shù)據(jù)庫.查詢?(查詢類SQL語句))
          ????????????  例句:外部數(shù)據(jù)庫1.首記錄前?(記錄集句柄)
          ????????????  ③、外部數(shù)據(jù)庫.尾記錄后?(記錄集句柄)
          ????????????  ④、外部數(shù)據(jù)庫.到首記錄?(記錄集句柄)
          ????????????  ⑤、外部數(shù)據(jù)庫.到尾記錄?(記錄集句柄)
          ????????????  ⑥、外部數(shù)據(jù)庫.到前一記錄?(記錄集句柄)
          ????????????  ⑦、外部數(shù)據(jù)庫.到后一記錄?(記錄集句柄)
          ????????????  ⑧、外部數(shù)據(jù)庫.讀?(記錄集句柄,字段名稱或位置)
          ????????????  例句:語文編輯框.內(nèi)容?=?到文本?(外部數(shù)據(jù)庫1.讀?(記錄集句柄,?“語文”))
          ????????????  ⑵、對(duì)外部數(shù)據(jù)庫進(jìn)行編輯的方法。
          ????????????  所謂對(duì)外部數(shù)據(jù)庫的編輯,就是變更改動(dòng)外部數(shù)據(jù)庫本身,包括添加、更新、刪除等,對(duì)數(shù)據(jù)庫進(jìn)行編輯不必通過記錄集。所有非查詢類SQL語句都嵌入下面這個(gè)語句來執(zhí)行:
          ????????????  外部數(shù)據(jù)庫.執(zhí)行?(非查詢類SQL語句)
          ????????????  ①、添加記錄,其語法如下:
          ????????????  外部數(shù)據(jù)庫.執(zhí)行?(“insert?into?表名稱(字段1,字段2...)?values?(字段值1,字段值2...)?”)
          ????????????  例句:
          ????????????  外部數(shù)據(jù)庫1.執(zhí)行?(“INSERT?INTO?chj?”?+?“(學(xué)號(hào),姓名,語文,數(shù)學(xué),英語)”?+?“?valueS?”?+?
          ????????????“(”?+?學(xué)號(hào)編輯框.內(nèi)容?+?“,'”?+?姓名編輯框.內(nèi)容?+?“','”?+?語文編輯框.內(nèi)容?+?“','”?+?
          ????????????數(shù)學(xué)編輯框.內(nèi)容?+?“','”?+?英語編輯框.內(nèi)容?+?“')”)
          ????????????  ②、更新記錄,其語法如下:
          ????????????  外部數(shù)據(jù)庫.執(zhí)行?(“UPDATE?表名稱?SET?字段1=字段值1,字段2=字段值2...WHERE?條件式”)?
          ????????????  例句:
          ????????????  外部數(shù)據(jù)庫1.執(zhí)行?(“UPDATE?chj?SET?學(xué)號(hào)=”?+?“'”?+?學(xué)號(hào)編輯框.內(nèi)容?+?“',”?+?“姓名=”?
          ????????????+?“'”?+?姓名編輯框.內(nèi)容?+?“',”?+?“語文=”?+?“'”?+?語文編輯框.內(nèi)容?+?“',”?+?“數(shù)學(xué)=”?
          ????????????+?“'”?+?數(shù)學(xué)編輯框.內(nèi)容?+?“',”?+?“英語=”?+?“'”?+?英語編輯框.內(nèi)容?+?“'?”?+?“WHERE?
          ????????????姓名=”?+?“'”?+?姓名1?+?“'?”?+?“AND?語文=”?+?語文1?+?“AND?數(shù)學(xué)=”?+?數(shù)學(xué)1?+?“AND?
          ????????????英語=”?+?英語1?+?“AND?學(xué)號(hào)=”?+?學(xué)號(hào)1)
          ????????????  ③、刪除記錄,其語法如下:
          ????????????  外部數(shù)據(jù)庫.執(zhí)行?(“DELETE?*?FROM?表名稱?WHERE?條件式”)
          ????????????  例句:
          ????????????  外部數(shù)據(jù)庫.執(zhí)行?(“外部數(shù)據(jù)庫1.執(zhí)行?(“DELETE?*?FROM?chj?”?+?“WHERE?姓名=”?+?“'”?+?
          ????????????姓名1?+?“'?”?+?“AND?語文=”?+?語文1?+?“AND?數(shù)學(xué)=”?+?數(shù)學(xué)1?+?“AND?英語=”?+?英語1?+?
          ????????????“AND?學(xué)號(hào)=”?+?學(xué)號(hào)1)”)
          posted @ 2007-01-19 12:17 Lansing 閱讀(1644) | 評(píng)論 (3)編輯 收藏
          Java虛擬機(jī)

          一、什么是Java虛擬機(jī)


          Java虛擬機(jī)是一個(gè)想象中的機(jī)器,在實(shí)際的計(jì)算機(jī)上通過軟件模擬來實(shí)現(xiàn)。Java虛擬機(jī)有自己想象中的硬件,如處理器、堆棧、寄存器等,還具有相應(yīng)的指令系統(tǒng)。


          1.為什么要使用Java虛擬機(jī)


          Java語言的一個(gè)非常重要的特點(diǎn)就是與平臺(tái)的無關(guān)性。而使用Java虛擬機(jī)是實(shí)現(xiàn)這一特點(diǎn)的關(guān)鍵。一般的高級(jí)語言如果要在不同的平臺(tái)上運(yùn)行,至少需要編譯成不同的目標(biāo)代碼。而引入Java語言虛擬機(jī)后,Java語言在不同平臺(tái)上運(yùn)行時(shí)不需要重新編譯。Java語言使用模式Java虛擬機(jī)屏蔽了與具體平臺(tái)相關(guān)的信息,使得Java語言編譯程序只需生成在Java虛擬機(jī)上運(yùn)行的目標(biāo)代碼(字節(jié)碼),就可以在多種平臺(tái)上不加修改地運(yùn)行。Java虛擬機(jī)在執(zhí)行字節(jié)碼時(shí),把字節(jié)碼解釋成具體平臺(tái)上的機(jī)器指令執(zhí)行。


          2.誰需要了解Java虛擬機(jī)


          Java虛擬機(jī)是Java語言底層實(shí)現(xiàn)的基礎(chǔ),對(duì)Java語言感興趣的人都應(yīng)對(duì)Java虛擬機(jī)有個(gè)大概的了解。這有助于理解Java語言的一些性質(zhì),也有助于使用Java語言。對(duì)于要在特定平臺(tái)上實(shí)現(xiàn)Java虛擬機(jī)的軟件人員,Java語言的編譯器作者以及要用硬件芯片實(shí)現(xiàn)Java虛擬機(jī)的人來說,則必須深刻理解Java虛擬機(jī)的規(guī)范。另外,如果你想擴(kuò)展Java語言,或是把其它語言編譯成Java語言的字節(jié)碼,你也需要深入地了解Java虛擬機(jī)。


          3.Java虛擬機(jī)支持的數(shù)據(jù)類型


          Java虛擬機(jī)支持Java語言的基本數(shù)據(jù)類型如下:


          byte://1字節(jié)有符號(hào)整數(shù)的補(bǔ)碼
          short://2字節(jié)有符號(hào)整數(shù)的補(bǔ)碼
          int://4字節(jié)有符號(hào)整數(shù)的補(bǔ)碼
          long://8字節(jié)有符號(hào)整數(shù)的補(bǔ)碼
          float://4字節(jié)IEEE754單精度浮點(diǎn)數(shù)
          double://8字節(jié)IEEE754雙精度浮點(diǎn)數(shù)
          char://2字節(jié)無符號(hào)Unicode字符


          幾乎所有的Java類型檢查都是在編譯時(shí)完成的。上面列出的原始數(shù)據(jù)類型的數(shù)據(jù)在Java執(zhí)行時(shí)不需要用硬件標(biāo)記。操作這些原始數(shù)據(jù)類型數(shù)據(jù)的字節(jié)碼(指令)本身就已經(jīng)指出了操作數(shù)的數(shù)據(jù)類型,例如iadd、ladd、fadd和dadd指令都是把兩個(gè)數(shù)相加,其操作數(shù)類型別是int、long、float和double。虛擬機(jī)沒有給boolean(布爾)類型設(shè)置單獨(dú)的指令。boolean型的數(shù)據(jù)是由integer指令,包括integer返回來處理的。boolean型的數(shù)組則是用byte數(shù)組來處理的。虛擬機(jī)使用IEEE754格式的浮點(diǎn)數(shù)。不支持IEEE格式的較舊的計(jì)算機(jī),在運(yùn)行Java數(shù)值計(jì)算程序時(shí),可能會(huì)非常慢。


          虛擬機(jī)支持的其它數(shù)據(jù)類型包括:
          object//對(duì)一個(gè)Javaobject(對(duì)象)的4字節(jié)引用
          returnAddress//4字節(jié),用于jsr/ret/jsr-w/ret-w指令
          注:Java數(shù)組被當(dāng)作object處理。


          虛擬機(jī)的規(guī)范對(duì)于object內(nèi)部的結(jié)構(gòu)沒有任何特殊的要求。在Sun公司的實(shí)現(xiàn)中,對(duì)object的引用是一個(gè)句柄,其中包含一對(duì)指針:一個(gè)指針指向該object的方法表,另一個(gè)指向該object的數(shù)據(jù)。用Java虛擬機(jī)的字節(jié)碼表示的程序應(yīng)該遵守類型規(guī)定。Java虛擬機(jī)的實(shí)現(xiàn)應(yīng)拒絕執(zhí)行違反了類型規(guī)定的字節(jié)碼程序。Java虛擬機(jī)由于字節(jié)碼定義的限制似乎只能運(yùn)行于32位地址空間的機(jī)器上。但是可以創(chuàng)建一個(gè)Java虛擬機(jī),它自動(dòng)地把字節(jié)碼轉(zhuǎn)換成64位的形式。從Java虛擬機(jī)支持的數(shù)據(jù)類型可以看出,Java對(duì)數(shù)據(jù)類型的內(nèi)部格式進(jìn)行了嚴(yán)格規(guī)定,這樣使得各種Java虛擬機(jī)的實(shí)現(xiàn)對(duì)數(shù)據(jù)的解釋是相同的,從而保證了Java的與平臺(tái)無關(guān)性和可
          移植性。


          二、Java虛擬機(jī)體系結(jié)構(gòu)


          Java虛擬機(jī)由五個(gè)部分組成:一組指令集、一組寄存器、一個(gè)棧、一個(gè)無用單元收集堆(Garbage-collected-heap)、一個(gè)方法區(qū)域。這五部分是Java虛擬機(jī)的邏輯成份,不依賴任何實(shí)現(xiàn)技術(shù)或組織方式,但它們的功能必須在真實(shí)機(jī)器上以某種方式實(shí)現(xiàn)。


          1.Java指令集


          Java虛擬機(jī)支持大約248個(gè)字節(jié)碼。每個(gè)字節(jié)碼執(zhí)行一種基本的CPU運(yùn)算,例如,把一個(gè)整數(shù)加到寄存器,子程序轉(zhuǎn)移等。Java指令集相當(dāng)于Java程序的匯編語言。
          Java指令集中的指令包含一個(gè)單字節(jié)的操作符,用于指定要執(zhí)行的操作,還有0個(gè)或多個(gè)操作數(shù),提供操作所需的參數(shù)或數(shù)據(jù)。許多指令沒有操作數(shù),僅由一個(gè)單字節(jié)的操作符構(gòu)成。


          虛擬機(jī)的內(nèi)層循環(huán)的執(zhí)行過程如下:


          do{
          取一個(gè)操作符字節(jié);
          根據(jù)操作符的值執(zhí)行一個(gè)動(dòng)作;
          }while(程序未結(jié)束)


          由于指令系統(tǒng)的簡單性,使得虛擬機(jī)執(zhí)行的過程十分簡單,從而有利于提高執(zhí)行的效率。指令中操作數(shù)的數(shù)量和大小是由操作符決定的。如果操作數(shù)比一個(gè)字節(jié)大,那么它存儲(chǔ)的順序是高位字節(jié)優(yōu)先。例如,一個(gè)16位的參數(shù)存放時(shí)占用兩個(gè)字節(jié),其值為:


          第一個(gè)字節(jié)*256+第二個(gè)字節(jié)字節(jié)碼指令流一般只是字節(jié)對(duì)齊的。指令tabltch和lookup是例外,在這兩條指令內(nèi)部要求強(qiáng)制的4字節(jié)邊界對(duì)齊。


          2.寄存器


          Java虛擬機(jī)的寄存器用于保存機(jī)器的運(yùn)行狀態(tài),與微處理器中的某些專用寄存器類似。


          Java虛擬機(jī)的寄存器有四種:
          pc:Java程序計(jì)數(shù)器。
          optop:指向操作數(shù)棧頂端的指針。
          frame:指向當(dāng)前執(zhí)行方法的執(zhí)行環(huán)境的指針。
          vars:指向當(dāng)前執(zhí)行方法的局部變量區(qū)第一個(gè)變量的指針。


          Java虛擬機(jī)


          Java虛擬機(jī)是棧式的,它不定義或使用寄存器來傳遞或接受參數(shù),其目的是為了保證指令集的簡潔性和實(shí)現(xiàn)時(shí)的高效性(特別是對(duì)于寄存器數(shù)目不多的處理器)。
          所有寄存器都是32位的。


          3.棧


          Java虛擬機(jī)的棧有三個(gè)區(qū)域:局部變量區(qū)、運(yùn)行環(huán)境區(qū)、操作數(shù)區(qū)。


          (1)局部變量區(qū) 每個(gè)Java方法使用一個(gè)固定大小的局部變量集。它們按照與vars寄存器的字偏移量來尋址。局部變量都是32位的。長整數(shù)和雙精度浮點(diǎn)數(shù)占據(jù)了兩個(gè)局部變量的空間,卻按照第一個(gè)局部變量的索引來尋址。(例如,一個(gè)具有索引n的局部變量,如果是一個(gè)雙精度浮點(diǎn)數(shù),那么它實(shí)際占據(jù)了索引n和n+1所代表的存儲(chǔ)空間。)虛擬機(jī)規(guī)范并不要求在局部變量中的64位的值是64位對(duì)齊的。虛擬機(jī)提供了把局部變量中的值裝載到操作數(shù)棧的指令,也提供了把操作數(shù)棧中的值寫入局部變量的指令。


          (2)運(yùn)行環(huán)境區(qū) 在運(yùn)行環(huán)境中包含的信息用于動(dòng)態(tài)鏈接,正常的方法返回以及異常傳播。


          ·動(dòng)態(tài)鏈接
          運(yùn)行環(huán)境包括對(duì)指向當(dāng)前類和當(dāng)前方法的解釋器符號(hào)表的指針,用于支持方法代碼的動(dòng)態(tài)鏈接。方法的class文件代碼在引用要調(diào)用的方法和要訪問的變量時(shí)使用符號(hào)。動(dòng)態(tài)鏈接把符號(hào)形式的方法調(diào)用翻譯成實(shí)際方法調(diào)用,裝載必要的類以解釋還沒有定義的符號(hào),并把變量訪問翻譯成與這些變量運(yùn)行時(shí)的存儲(chǔ)結(jié)構(gòu)相應(yīng)的偏移地址。動(dòng)態(tài)鏈接方法和變量使得方法中使用的其它類的變化不會(huì)影響到本程序的代碼。


          ·正常的方法返回
          如果當(dāng)前方法正常地結(jié)束了,在執(zhí)行了一條具有正確類型的返回指令時(shí),調(diào)用的方法會(huì)得到一個(gè)返回值。執(zhí)行環(huán)境在正常返回的情況下用于恢復(fù)調(diào)用者的寄存器,并把調(diào)用者的程序計(jì)數(shù)器增加一個(gè)恰當(dāng)?shù)臄?shù)值,以跳過已執(zhí)行過的方法調(diào)用指令,然后在調(diào)用者的執(zhí)行環(huán)境中繼續(xù)執(zhí)行下去。


          ·異常和錯(cuò)誤傳播
          異常情況在Java中被稱作Error(錯(cuò)誤)或Exception(異常),是Throwable類的子類,在程序中的原因是:①動(dòng)態(tài)鏈接錯(cuò),如無法找到所需的class文件。②運(yùn)行時(shí)錯(cuò),如對(duì)一個(gè)空指針的引用


          ·程序使用了throw語句。
          當(dāng)異常發(fā)生時(shí),Java虛擬機(jī)采取如下措施:
          ·檢查與當(dāng)前方法相聯(lián)系的catch子句表。每個(gè)catch子句包含其有效指令范圍,能夠處理的異常類型,以及處理異常的代碼塊地址。
          ·與異常相匹配的catch子句應(yīng)該符合下面的條件:造成異常的指令在其指令范圍之內(nèi),發(fā)生的異常類型是其能處理的異常類型的子類型。如果找到了匹配的catch子句,那么系統(tǒng)轉(zhuǎn)移到指定的異常處理塊處執(zhí)行;如果沒有找到異常處理塊,重復(fù)尋找匹配的catch子句的過程,直到當(dāng)前方法的所有嵌套的catch子句都被檢查過。
          ·由于虛擬機(jī)從第一個(gè)匹配的catch子句處繼續(xù)執(zhí)行,所以catch子句表中的順序是很重要的。因?yàn)镴ava代碼是結(jié)構(gòu)化的,因此總可以把某個(gè)方法的所有的異常處理器都按序排列到一個(gè)表中,對(duì)任意可能的程序計(jì)數(shù)器的值,都可以用線性的順序找到合適的異常處理塊,以處理在該程序計(jì)數(shù)器值下發(fā)生的異常情況。
          ·如果找不到匹配的catch子句,那么當(dāng)前方法得到一個(gè)"未截獲異常"的結(jié)果并返回到當(dāng)前方法的調(diào)用者,好像異常剛剛在其調(diào)用者中發(fā)生一樣。如果在調(diào)用者中仍然沒有找到相應(yīng)的異常處理塊,那么這種錯(cuò)誤傳播將被繼續(xù)下去。如果錯(cuò)誤被傳播到最頂層,那么系統(tǒng)將調(diào)用一個(gè)缺省的異常處理塊。
          (3)操作數(shù)棧區(qū) 機(jī)器指令只從操作數(shù)棧中取操作數(shù),對(duì)它們進(jìn)行操作,并把結(jié)果返回到棧中。選擇棧結(jié)構(gòu)的原因是:在只有少量寄存器或非通用寄存器的機(jī)器(如Intel486)上,也能夠高效地模擬虛擬機(jī)的行為。操作數(shù)棧是32位的。它用于給方法傳遞參數(shù),并從方法接收結(jié)果,也用于支持操作的參數(shù),并保存操作的結(jié)果。例如,iadd指令將兩個(gè)整數(shù)相加。相加的兩個(gè)整數(shù)應(yīng)該是操作數(shù)棧頂?shù)膬蓚€(gè)字。這兩個(gè)字是由先前的指令壓進(jìn)堆棧的。這兩個(gè)整數(shù)將從堆棧彈出、相加,并把結(jié)果壓回到操作數(shù)棧中。


          每個(gè)原始數(shù)據(jù)類型都有專門的指令對(duì)它們進(jìn)行必須的操作。每個(gè)操作數(shù)在棧中需要一個(gè)存儲(chǔ)位置,除了long和double型,它們需要兩個(gè)位置。操作數(shù)只能被適用于其類型的操作符所操作。例如,壓入兩個(gè)int類型的數(shù),如果把它們當(dāng)作是一個(gè)long類型的數(shù)則是非法的。在Sun的虛擬機(jī)實(shí)現(xiàn)中,這個(gè)限制由字節(jié)碼驗(yàn)證器強(qiáng)制實(shí)行。但是,有少數(shù)操作(操作符dupe和swap),用于對(duì)運(yùn)行時(shí)數(shù)據(jù)區(qū)進(jìn)行操作時(shí)是不考慮類型的。


          4.無用單元收集堆


          Java的堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),類的實(shí)例(對(duì)象)從中分配空間。Java語言具有無用單元收集能力:它不給程序員顯式釋放對(duì)象的能力。Java不規(guī)定具體使用的無用單元收集算法,可以根據(jù)系統(tǒng)的需求使用各種各樣的算法。


          5.方法區(qū)


          方法區(qū)與傳統(tǒng)語言中的編譯后代碼或是Unix進(jìn)程中的正文段類似。它保存方法代碼(編譯后的java代碼)和符號(hào)表。在當(dāng)前的Java實(shí)現(xiàn)中,方法代碼不包括在無用單元收集堆中,但計(jì)劃在將來的版本中實(shí)現(xiàn)。每個(gè)類文件包含了一個(gè)Java類或一個(gè)Java界面的編譯后的代碼。可以說類文件是Java語言的執(zhí)行代碼文件。為了保證類文件的平臺(tái)無關(guān)性,Java虛擬機(jī)規(guī)范中對(duì)類文件的格式也作了詳細(xì)的說明。其具體細(xì)節(jié)請參考Sun公司的Java虛擬機(jī)規(guī)范。

          posted @ 2007-01-18 14:27 Lansing 閱讀(596) | 評(píng)論 (1)編輯 收藏
          Sun 提供的標(biāo)準(zhǔn) Java 開發(fā)包(JDK)沒有提供創(chuàng)建特定于平臺(tái)的可執(zhí)行文件的工具(一點(diǎn)都不吃驚,這是真的)。然而,其實(shí)有很多方法能夠幫助你實(shí)現(xiàn)這一想法。
            
            第三方工具
            一種方法是使用第三方商業(yè)工具或免費(fèi)工具將 Java 應(yīng)用程序打包為一個(gè)可執(zhí)行文件。
            
            下面是價(jià)格和特性都不同的兩個(gè)工具,但是在 Web 上還有其它幾個(gè)第三方工具可以免費(fèi)下載。
            
            http://www.bysoft.se/sureshot/exej/
            http://www.duckware.com/jexepack/
            使用商業(yè)安裝程序(installer)
            InstallAnywhere 是一個(gè)常用的安裝程序,它將管理應(yīng)用程序的安裝過程,并將應(yīng)用程序打包為可執(zhí)行程序。
            
            使用 .jar
            除了以上方法之外,還可以將應(yīng)用程序打包為一個(gè)可執(zhí)行的 .jar 文件,而不是一個(gè) .exe 文件。在這篇文章中我將不詳細(xì)介紹這種方法,你可以在這里找到一個(gè)非常棒的在線教程
            
            你需要做的最重要的一件事是指定在 .jar 文件中哪個(gè)類是應(yīng)用程序的入口點(diǎn)。例如,對(duì)你的應(yīng)用程序來說就是具有一個(gè) public static void main(String[] args) 方法的引導(dǎo)類。可以在 .jar 表示文件的 Main-Class 頭部信息中提供這些信息。這個(gè)頭部信息的通用形式為:Main-Class: classname,其中 classname 是應(yīng)用程序的入口點(diǎn)的類名稱。
            
            使用 Java Webstart
            Java Webstart 是標(biāo)準(zhǔn) Java 運(yùn)行時(shí)環(huán)境(JRE)的隱藏的寶物,自從版本 1.3 開始,JRE 就包含了 Java Webstart。它是一個(gè)簡單但功能強(qiáng)大且靈活的將應(yīng)用程序部署到任何平臺(tái)的方法。
            
            Webstart 允許應(yīng)用程序的用戶從他們的瀏覽器、電子郵件或桌面啟動(dòng)和管理應(yīng)用程序。Java Webstart 的一個(gè)主要優(yōu)點(diǎn)是一旦應(yīng)用程序被安裝,在每次啟動(dòng)它時(shí),它都將會(huì)檢查用戶是否在運(yùn)行最新版本的應(yīng)用程序。如果不是,應(yīng)用程序?qū)⑼ㄟ^網(wǎng)絡(luò)裝載新版本到桌面然后執(zhí)行,因此解決了軟件傳播問題。
            
            如果你的應(yīng)用程序已經(jīng)有很多用戶的話,這一點(diǎn)就尤其重要。還有很重要的一點(diǎn)是,它能夠檢查用戶的本地桌面環(huán)境,并能保證他們安裝了正確的 JRE 版本來運(yùn)行你的應(yīng)用程序。
            
            Java Webstart 本身有一系列文章,所以我建議你訪問 Java Webstart Web 站點(diǎn)查看更多文檔和教程。
            
            結(jié)束語
            前兩種方法可能會(huì)滿足你對(duì)這個(gè)問題的需要,但是我強(qiáng)烈建議你仔細(xì)看一下 Java Webstart。它是 Java 標(biāo)準(zhǔn)的一部分,并且能夠在所有平臺(tái)下一致工作。我比較喜歡這個(gè)應(yīng)用程序打包方法。
          posted @ 2007-01-18 14:21 Lansing 閱讀(707) | 評(píng)論 (0)編輯 收藏
               摘要: Lucene In Action ch 6(I) 筆記 --自定義排序 ----- 2006-2-16?????? 使用 Lucene 來搜索內(nèi)容,搜索結(jié)果的顯示順序當(dāng)然是比較重要的.Lucene中Build-in的幾個(gè)排序定義在大多數(shù)情況下是不適合我們使用的.要適合自己的應(yīng)用程序的場景,就只能自定義排序功能,本節(jié)...  閱讀全文
          posted @ 2007-01-05 10:27 Lansing 閱讀(735) | 評(píng)論 (0)編輯 收藏
               摘要: Lucene In Action ch 5 筆記 --高級(jí)搜索技術(shù) ----- 2006-2-15 該章介紹了Lucene的一些高級(jí)技術(shù),如 結(jié)果排序,搜索多個(gè)Index,過慮技術(shù)....下面就看看這些高級(jí)技巧吧. I.Sorting search results ...  閱讀全文
          posted @ 2007-01-05 10:25 Lansing 閱讀(617) | 評(píng)論 (0)編輯 收藏
               摘要: Lucene In Action ch 4 筆記(I) -- Analysis ----- 2006-2-12 本章詳細(xì)的討論了 Lucene的分析處理過程和幾個(gè)Analyzer. 在indexing過程中要把需要indexing的text分析處理一下, 經(jīng)過處理和切詞 然后建立index. 而不通的Ana...  閱讀全文
          posted @ 2007-01-05 10:14 Lansing 閱讀(1098) | 評(píng)論 (0)編輯 收藏
               摘要: 1. 實(shí)現(xiàn)一個(gè)簡單的search feature ?? 在本章中只限于討論簡單Lucene 搜索API, 有下面幾個(gè)相關(guān)的類: ?Lucene 基本搜索API: 類 ...  閱讀全文
          posted @ 2007-01-05 10:11 Lansing 閱讀(849) | 評(píng)論 (0)編輯 收藏
               摘要: Lucene In Action ch2 系統(tǒng)的講解了 indexing,下面就來看看吧. 1,indexing 的處理過程. ? 首先要把indexing的數(shù)據(jù)轉(zhuǎn)換為text,因?yàn)長ucene只能索引text,然后由Analysis來過慮text,把一些ch1中提到的所謂的stop words 過濾掉, 然后建...  閱讀全文
          posted @ 2007-01-05 10:10 Lansing 閱讀(845) | 評(píng)論 (0)編輯 收藏

          若人生是直線前進(jìn)的,
          那么命中注定有若干的交點(diǎn),
          認(rèn)識(shí)注定的人,
          欣賞注定的風(fēng)景...

          可人生還是有選擇的,
          那么道路也就多了些分叉口,
          錯(cuò)過注定的人,
          錯(cuò)過注定的風(fēng)景...

          若我曾經(jīng)再某個(gè)分叉路口選錯(cuò)了方向卻遇到了注定的人,該感謝上蒼賜予我的福氣吧!
          可是人生又有了新的岔口,選擇有些艱難,但是面對(duì)幸福我很堅(jiān)定!

          該怎么愛你

          我聽 過你的微笑
          就忘了 所有動(dòng)蕩
          當(dāng)我靠過你的 那雙肩膀
          也就忘了 塵土飛楊
          我只是 一棵小草
          孤單的 微不足道
          當(dāng)你搬進(jìn)我的小小國度
          我才相信 平凡的美好
          該怎么愛你 我才不會(huì)忘
          你的溫度 來過身旁
          就算哪一天 失去了方向
          愛過的 完整的 還在心上
          該怎么愛你 才可以盼望
          那種幸福 遠(yuǎn)遠(yuǎn)流長
          就怕這時(shí)間 讓我趕不上
          說一句 只一句 我曾到過天堂
          我相信最燦爛的一秒
          是守著你的眼光
          不是熱烈擁抱
          不是驚濤駭浪
          我相信最美麗的風(fēng)光
          是在彼此身旁
          有另一雙肩膀
          一起慢慢變老

          posted @ 2006-12-13 14:22 Lansing 閱讀(322) | 評(píng)論 (0)編輯 收藏
          ?本文主要面向具體使用,適用于已熟悉java編程的lucene初學(xué)者。
          1. Lucene的簡介


          1.1 Lucene 歷史


          ????? org.apache.lucene包是純java語言的全文索引檢索工具包。
          ????? Lucene的作者是資深的全文索引/檢索專家,最開始發(fā)布在他本人的主頁上,2001年10月貢獻(xiàn)給APACHE,成為APACHE基金jakarta的一個(gè)子項(xiàng)目。
          ????? 目前,lucene廣泛用于全文索引/檢索的項(xiàng)目中。
          ????? lucene也被翻譯成C#版本,目前發(fā)展為Lucene.Net(不過最近好象有流產(chǎn)的消息)。


          1.2 Lucene 原理


          ?????? lucene的檢索算法屬于索引檢索,即用空間來換取時(shí)間,對(duì)需要檢索的文件、字符流進(jìn)行全文索引,在檢索的時(shí)候?qū)λ饕M(jìn)行快速的檢索,得到檢索位置,這個(gè)位置記錄檢索詞出現(xiàn)的文件路徑或者某個(gè)關(guān)鍵詞。
          ?????? 在使用數(shù)據(jù)庫的項(xiàng)目中,不使用數(shù)據(jù)庫進(jìn)行檢索的原因主要是:數(shù)據(jù)庫在非精確查詢的時(shí)候使用查詢語言“l(fā)ike %keyword%”,對(duì)數(shù)據(jù)庫進(jìn)行查詢是對(duì)所有記錄遍歷,并對(duì)字段進(jìn)行“%keyword%”匹配,在數(shù)據(jù)庫的數(shù)據(jù)龐大以及某個(gè)字段存儲(chǔ)的數(shù)據(jù)量龐大的時(shí)候,這種遍歷是致命的,它需要對(duì)所有的記錄進(jìn)行匹配查詢。因此,lucene主要適用于文檔集的全文檢索,以及海量數(shù)據(jù)庫的模糊檢索,特別是對(duì)數(shù)據(jù)庫的xml或者大數(shù)據(jù)的字符類型。


          2.Lucene的下載和配置


          2.1 Lucene的下載


          ?????? lucene在jakarta項(xiàng)目中的發(fā)布主頁:http://jakarta.apache.org/lucene/docs/index.html。以下主要針對(duì)windows用戶,其它用戶請?jiān)谏厦娴牡刂分胁檎蚁嚓P(guān)下載。


          ?????? lucene的.jar包的下載(包括.jar和一個(gè)范例demo):
          http://apache.oregonstate.edu/jakarta/lucene/binaries/lucene-1.4-final.zip


          ??????? lucene的源代碼下載:
          http://www.signal42.com/mirrors/apache/jakarta/lucene/source/lucene-1.4-final-src.zip


          ?lucene的api地址:http://jakarta.apache.org/lucene/docs/api/index.html


          ?本文使用lucene版本:lucene-1.4-final.jar。


          2.2 lucene的配置


          ??????? 首先請確定你的機(jī)子已經(jīng)進(jìn)行了java使用環(huán)境的基本配置,即確保在某個(gè)平臺(tái)下能夠運(yùn)行java源代碼,否則請查閱相關(guān)文檔進(jìn)行配置。
          ??????? 接下來進(jìn)入lucene的配置:
          ??????? 普通使用者:在環(huán)境變量的CLASSPATH中添加lucene的位置。比如:“D:\java \lucene-1.4-final\lucene-1.4-final.jar;”。
          ?????? jbuilder使用者:在“Project”--“Project Properties”--“Required Libraries”進(jìn)行添加。
          ?????? Jsp使用者:也可以直接將lucene-1.4-final.jar文件放到\WEB-INF\classes下。


          3. Lucene 的范例(Demo )


          3.1 Demo說明

          ?????
          ??????? 可以得到的Demo包括:lucene-demos-1.4-final、XMLIndexingDemo,lucene-demos-1.4-final中包括對(duì)普通文件和html文件的兩種索引,XMLIndexingDemo針對(duì)xml文件的索引。他們的區(qū)別主要在于:對(duì)普通文件進(jìn)行索引時(shí)只要對(duì)文件的全文進(jìn)行索引,而針對(duì)html、xml文件時(shí),對(duì)標(biāo)簽類型不能進(jìn)行索引,在實(shí)現(xiàn)上:html、xml的索引需要額外的數(shù)據(jù)流分析器,以分析哪些內(nèi)容有用哪些無用。因此,在后兩者實(shí)現(xiàn)上,索引的時(shí)間額外開支,甚至超過索引本身時(shí)間,而檢索時(shí)間沒有區(qū)別。


          ??????? 以上Demo中,lucene-demos-1.4-final自帶于lucene-1.4-final.zip中,XMLIndexingDemo的下載地址:
          http://cvs.apache.org/viewcvs.cgi/jakarta-lucene-sandbox/contributions/XML-Indexing-Demo/


          3.2 Demo的運(yùn)行


          ????????首先將demo.jar的路徑添加如環(huán)境變量的CLASSPATH中,例如:“D:\java\lucene-1.4-final\lucene-demos-1.4-final.jar;”,同時(shí)確保已經(jīng)添加lucene-1.4-final.jar。


          ????????然后進(jìn)行文件的全文索引,在dos控制臺(tái)中,輸入命令“java org.apache.lucene.demo.IndexFiles {full-path-to-lucene}/src”,后面的路徑為所要進(jìn)行索引的文件夾,例如:“java org.apache.lucene.demo.IndexFiles c:\test”。


          ??????? 接著對(duì)索引進(jìn)行檢索,敲入“java org.apache.lucene.demo.SearchFiles”,在提示“Query:”后輸入檢索詞,程序?qū)⑦M(jìn)行檢索列出檢索得到的結(jié)果(檢索詞出現(xiàn)的文件路徑)。
          ?
          ?????? 其他Demo的運(yùn)行請參考\docs\demo.html。
          ?????? 在運(yùn)行Demo后請閱讀Demo的源代碼以便深入學(xué)習(xí)。

          4. 利用Lucene進(jìn)行索引


          ??????? 進(jìn)行l(wèi)ucene的熟悉后,我們將學(xué)習(xí)如何使用Lucene。
          ?一段索引的應(yīng)用實(shí)例:

          ??? //需要捕捉IOException異常
          ??? //建立一個(gè)IndexWriter,索引保存目錄為“index”
          ??? String[] stopStrs = {
          ??????? "他奶奶的", "fuck"};
          ??? StandardAnalyzer analyzer = new StandardAnalyzer(stopStrs);
          ??? IndexWriter writer = new IndexWriter("index", analyzer, true);
          ???
          ??? //添加一條文檔
          ??? Document doc = new Document();
          ??? doc.add(Field.UnIndexed("id", "1"));//“id”為字段名,“1”為字段值
          ??? doc.add(Field.Text("text", "fuck,他奶奶的,入門與使用"));
          ??? writer.addDocument(doc);
          ???
          ??? //索引完成后的處理
          ??? writer.optimize();
          ??? writer.close();

          ?????? 看完這段實(shí)例后,我們開始熟悉lucene的使用:

          4.1 Lucene的索引接口


          ?在學(xué)習(xí)索引的時(shí)候,首先需要熟悉幾個(gè)接口:


          4.1.1分析器Analyzer


          ??????? 分析器主要工作是篩選,一段文檔進(jìn)來以后,經(jīng)過它,出去的時(shí)候只剩下那些有用的部分,其他則剔除。而這個(gè)分析器也可以自己根據(jù)需要而編寫。
          ??????? org.apache.lucene.analysis.Analyzer:這是一個(gè)虛構(gòu)類,以下兩個(gè)借口均繼承它而來。


          ????????org.apache.lucene.analysis.SimpleAnalyzer:分析器,支持最簡單拉丁語言。


          ????????org.apache.lucene.analysis.standard.StandardAnalyzer:標(biāo)準(zhǔn)分析器,除了拉丁語言還支持亞洲語言,并在一些匹配功能上進(jìn)行完善。在這個(gè)接口中還有一個(gè)很重要的構(gòu)造函數(shù):StandardAnalyzer(String[] stopWords),可以對(duì)分析器定義一些使用詞語,這不僅可以免除檢索一些無用信息,而且還可以在檢索中定義禁止的政治性、非法性的檢索關(guān)鍵詞。


          4.1.2 IndexWriter


          ????????IndexWriter的構(gòu)造函數(shù)有三種接口,針對(duì)目錄Directory、文件File、文件路徑String三種情況。
          例如IndexWriter(String path, Analyzer a, boolean create),path為文件路徑,a為分析器,create標(biāo)志是否重建索引(true:建立或者覆蓋已存在的索引,false:擴(kuò)展已存在的索引。)
          ?????? 一些重要的方法:

          接口名

          備注

          addDocument(Document doc)

          索引添加一個(gè)文檔

          addIndexes(Directory[] dirs)

          將目錄中已存在索引添加到這個(gè)索引

          addIndexes(IndexReader[] readers)

          將提供的索引添加到這個(gè)索引

          optimize()

          合并索引并優(yōu)化

          close()

          關(guān)閉


          ?????? IndexWriter為了減少大量的io維護(hù)操作,在每得到一定量的索引后建立新的小索引文件(筆者測試索引批量的最小單位為10),然后再定期將它們整合到一個(gè)索引文件中,因此在索引結(jié)束時(shí)必須進(jìn)行wirter. optimize(),以便將所有索引合并優(yōu)化。


          4.1.3 org.apache.lucene.document


          ?以下介紹兩種主要的類:
          ?a)org.apache.lucene.document.Document:
          ????????Document文檔類似數(shù)據(jù)庫中的一條記錄,可以由好幾個(gè)字段(Field)組成,并且字段可以套用不同的類型(詳細(xì)見b)。Document的幾種接口:
          ?

          接口名

          備注

          add(Field field)

          添加一個(gè)字段(Field)到Document

          String get(String name)

          從文檔中獲得一個(gè)字段對(duì)應(yīng)的文本

          Field getField(String name)

          由字段名獲得字段值

          Field[] getFields(String name)

          由字段名獲得字段值的集


          ?b)org.apache.lucene.document.Field
          ??????? 即上文所說的“字段”,它是Document的片段section。
          ??????? Field的構(gòu)造函數(shù):
          ?????? Field(String name, String string, boolean store, boolean index, boolean token)。
          ??????? Indexed:如果字段是Indexed的,表示這個(gè)字段是可檢索的。
          ????????Stored:如果字段是Stored的,表示這個(gè)字段的值可以從檢索結(jié)果中得到。
          ????????Tokenized:如果一個(gè)字段是Tokenized的,表示它是有經(jīng)過Analyzer轉(zhuǎn)變后成為一個(gè)tokens序列,在這個(gè)轉(zhuǎn)變過程tokenization中,Analyzer提取出需要進(jìn)行索引的文本,而剔除一些冗余的詞句(例如:a,the,they等,詳見org.apache.lucene.analysis.StopAnalyzer.ENGLISH_STOP_WORDS和org.apache.lucene.analysis.standard.StandardAnalyzer(String[] stopWords)的API)。Token是索引時(shí)候的基本單元,代表一個(gè)被索引的詞,例如一個(gè)英文單詞,或者一個(gè)漢字。因此,所有包含中文的文本都必須是Tokenized的。
          ???? Field的幾種接口:

          Name

          Stored

          Indexed

          Tokenized

          use

          Keyword(String name,

          ??????? String value)

          Y

          Y

          N

          date,url

          Text(String name, Reader value)

          N

          Y

          Y

          short text fields:

          title,subject

          Text(String name, String value)

          Y

          Y

          Y

          longer text fields,

          like “body”

          UnIndexed(String name,

          String value)

          Y

          N

          N

          ?

          UnStored(String name,

          ???????? String value)

          N

          Y

          Y

          ?

          ?


          5. 利用Lucene進(jìn)行檢索


          5.1 一段簡單的檢索代碼

          ?

          ??? //需要捕捉IOException,ParseException異常
          ??? //處理檢索條件
          ??? Query query = QueryParser.parse("入門", "text", analyzer);

          ??? //檢索
          ??? Searcher searcher = new IndexSearcher("./index");//"index"指定索引文件位置
          Hits hits = searcher.search(query);

          ??? //打印結(jié)果值集
          ??? for (int i = 0; i < hits.length(); i++) {
          ????? doc = hits.doc(i);
          ????? String id = doc.get("id");
          ????? System.out.println("found " + "入門" + " on the id:" + id);
          }

          ?

          5.2 利用Lucene的檢索接口


          5.2.1 Query與QueryParser


          ??????? 主要使用方法:
          QueryParser .parse(String query, String field, Analyzer analyzer),例如:
          Query query = QueryParser.parse("入門", "text", analyzer);
          "入門"為檢索詞, "text"為檢索的字段名, analyzer為分析器


          5.2.2 Hits與Searcher


          ?????? Hits的主要使用接口:
          ?

          接口名

          備注

          Doc(int n)

          返回第n個(gè)的文檔的所有字段

          length()

          返回這個(gè)集中的可用個(gè)數(shù)

          ?


          6. Lucene的其他使用


          6.1 Lucene 的索引修改


          ??????? 下面給出一段修改索引的代碼,請根據(jù)Lucene的API解讀:


          ? /**
          ?? * 對(duì)已有的索引添加新的一條索引
          ?? * @param idStr String:要修改的id
          ?? * @param doc Document:要修改的值
          ?? */
          ? public void addIndex(String idStr, String valueStr) {
          ??? StandardAnalyzer analyzer = new StandardAnalyzer();
          ??? IndexWriter writer = null;
          ??? try {
          ????? writer = new IndexWriter(indexPath, analyzer, false);
          ????? writer.mergeFactor = 2; //修正lucene 1.4.2 bug,不添加則不合并原有索引

          ?????? ?? Document doc = new Document();
          ????????? doc.add(Field.UnIndexed("id", idStr));//“id”為字段名,“1”為字段值
          ????????? doc.add(Field.Text("text", valueStr));
          ????? writer.addDocument(doc);

          ????? writer.optimize();
          ????? writer.close();
          ??? }
          ??? catch (IOException ioe) {
          ????? ioe.printStackTrace();
          ??? }
          ? }

          ? /**
          ?? * 刪除索引
          ?? *
          ?? * @param idStr String
          ?? */
          ? public void deleteIndex(String idStr) {
          ??? try {
          ????? Directory dirt = FSDirectory.getDirectory(indexPath, false);
          ????? IndexReader reader = IndexReader.open(dirt);
          ????? IndexXML.deleteIndex(idStr, reader);
          ????? reader.close();
          ????? dirt.close();
          ??? }
          ??? catch (IOException ioe) {
          ????? ioe.printStackTrace();
          ??? }
          ? }


          6.2 Lucene 的檢索結(jié)果排序


          ??????? Lucene的排序主要是對(duì)org.apache.lucene.search.Sort的使用。Sort可以直接根據(jù)字段Field生成,也可以根據(jù)標(biāo)準(zhǔn)的SortField生成,但是作為Sort的字段,必須符合以下的條件:唯一值以及Indexed。可以對(duì)Integers, Floats, Strings三種類型排序。
          ??????? 對(duì)整數(shù)型的ID檢索結(jié)果排序只要進(jìn)行以下的簡單操作:

          ?Sort sort = new Sort("id");
          Hits hits = searcher.search(query, sort);

          ?????? 用戶還可以根據(jù)自己定義更加復(fù)雜的排序,詳細(xì)請參考API。


          7 總結(jié)


          ??????? Lucene給java的全文索引檢索帶來了非常強(qiáng)大的力量,以上僅對(duì)Lucene進(jìn)行簡單的入門說明。

          posted @ 2006-11-08 14:59 Lansing 閱讀(351) | 評(píng)論 (0)編輯 收藏

          Lucene提供了方便您創(chuàng)建自建查詢的API,也通過QueryParser提供了強(qiáng)大的查詢語言。

          本文講述Lucene的查詢語句解析器支持的語法,Lucene的查詢語句解析器是使用JavaCC工

          具生成的詞法解析器,它將查詢字串解析為Lucene Query對(duì)象。
          項(xiàng)(Term)
          一條搜索語句被拆分為一些項(xiàng)(term)和操作符(operator)。項(xiàng)有兩種類型:單獨(dú)項(xiàng)和

          短語。
          單獨(dú)項(xiàng)就是一個(gè)單獨(dú)的單詞,例如"test" , "hello"。
          短語是一組被雙引號(hào)包圍的單詞,例如"hello dolly"。
          多個(gè)項(xiàng)可以用布爾操作符連接起來形成復(fù)雜的查詢語句(接下來您就會(huì)看到)。
          注意:Analyzer建立索引時(shí)使用的解析器和解析單獨(dú)項(xiàng)和短語時(shí)的解析器相同,因此選擇

          一個(gè)不會(huì)受查詢語句干擾的Analyzer非常重要。luence1.4的StandardAnalyzer的解析器已

          經(jīng)支持中文等亞洲國家的文字了,可以直接。標(biāo)準(zhǔn)的解析其不支持中文。

          域(Field)
          Lucene支持域。您可以指定在某一個(gè)域中搜索,或者就使用默認(rèn)域。域名及默認(rèn)域是具體

          索引器實(shí)現(xiàn)決定的。(怎么定制默認(rèn)域?)
          您可以這樣搜索域:域名+":"+搜索的項(xiàng)名。
          舉個(gè)例子,假設(shè)某一個(gè)Lucene索引包含兩個(gè)域,title和text,text是默認(rèn)域。如果您想查

          找標(biāo)題為"The Right Way"且含有"don't go this way"的文章,您可以輸入:
          title:"The Right Way" AND text:go
          或者
          title:"Do it right" AND right
          因?yàn)閠ext是默認(rèn)域,所以這個(gè)域名可以不行。
          注意:域名只對(duì)緊接于其后的項(xiàng)生效,所以
          title:Do it right
          只有"Do"屬于title域。"it"和"right"仍將在默認(rèn)域中搜索(這里是text域)。

          項(xiàng)修飾符(Term Modifiers)
          Lucene支持項(xiàng)修飾符以支持更寬范圍的搜索選項(xiàng)。
          用通配符搜索
          Lucene支持單個(gè)與多個(gè)字符的通配搜索。
          使用符號(hào)"?"表示單個(gè)任意字符的通配。
          使用符號(hào)"*"表示多個(gè)任意字符的通配。
          單個(gè)任意字符匹配的是所有可能單個(gè)字符。例如,搜索"text或者"test",可以這樣:

          te?t
          多個(gè)任意字符匹配的是0個(gè)及更多個(gè)可能字符。例如,搜索test, tests 或者 tester,可

          以這樣: test*
          您也可以在字符竄中間使用多個(gè)任意字符通配符。 te*t
          注意:您不能在搜索的項(xiàng)開始使用*或者?符號(hào)。

          模糊查詢
          Lucene支持基于Levenshtein Distance與Edit Distance算法的模糊搜索。要使用模糊搜索

          只需要在單獨(dú)項(xiàng)的最后加上符號(hào)"~"。例如搜索拼寫類似于"roam"的項(xiàng)這樣寫:
          roam~
          這次搜索將找到形如foam和roams的單詞。
          注意:使用模糊查詢將自動(dòng)得到增量因子(boost factor)為0.2的搜索結(jié)果.

          鄰近搜索(Proximity Searches)
          Lucene還支持查找相隔一定距離的單詞。鄰近搜索是在短語最后加上符號(hào)"~"。例如在文檔

          中搜索相隔10個(gè)單詞的"apache"和"jakarta",這樣寫: "jakarta apache"~10

          Boosting a Term
          Lucene provides the relevance level of matching documents based on the terms

          found. To boost a term use the caret, "^", symbol with a boost factor (a

          number) at the end of the term you are searching. The higher the boost factor,

          the more relevant the term will be.
          Lucene可以設(shè)置在搜索時(shí)匹配項(xiàng)的相似度。在項(xiàng)的最后加上符號(hào)"^"緊接一個(gè)數(shù)字(增量值

          ),表示搜索時(shí)的相似度。增量值越高,搜索到的項(xiàng)相關(guān)度越好。
          Boosting allows you to control the relevance of a document by boosting its

          term. For example, if you are searching for jakarta apache and you want the

          term "jakarta" to be more relevant boost it using the ^ symbol along with the

          boost factor next to the term. You would type:
          通過增量一個(gè)項(xiàng)可以控制搜索文檔時(shí)的相關(guān)度。例如如果您要搜索jakarta apache,同時(shí)

          您想讓"jakarta"的相關(guān)度更加好,那么在其后加上"^"符號(hào)和增量值,也就是您輸入:
          jakarta^4 apache
          This will make documents with the term jakarta appear more relevant. You can

          also boost Phrase Terms as in the example:
          這將使得生成的doucment盡可能與jakarta相關(guān)度高。您也可以增量短語,象以下這個(gè)例子

          一樣:
          "jakarta apache"^4 "jakarta lucene"

          By default, the boost factor is 1. Although, the boost factor must be positive,

          it can be less than 1 (i.e. .2)
          默認(rèn)情況下,增量值是1。增量值也可以小于1(例如0.2),但必須是有效的。

          布爾操作符
          布爾操作符可將項(xiàng)通過邏輯操作連接起來。Lucene支持AND, "+", OR, NOT 和 "-"這些操

          作符。(注意:布爾操作符必須全部大寫)

          OR
          OR操作符是默認(rèn)的連接操作符。這意味著如果兩個(gè)項(xiàng)之間沒有布爾操作符,就是使用OR操

          作符。OR操作符連接兩個(gè)項(xiàng),意味著查找含有任意項(xiàng)的文檔。這與集合并運(yùn)算相同。符號(hào)

          ||可以代替符號(hào)OR。
          搜索含有"jakarta apache" 或者 "jakarta"的文檔,可以使用這樣的查詢:
          "jakarta apache" jakarta 或者 "jakarta apache" OR jakarta

          AND
          AND操作符匹配的是兩項(xiàng)同時(shí)出現(xiàn)的文檔。這個(gè)與集合交操作相等。符號(hào)&&可以代替符號(hào)

          AND。
          搜索同時(shí)含有"jakarta apache" 與 "jakarta lucene"的文檔,使用查詢:
          "jakarta apache" AND "jakarta lucene"

          +
          "+"操作符或者稱為存在操作符,要求符號(hào)"+"后的項(xiàng)必須在文檔相應(yīng)的域中存在。
          搜索必須含有"jakarta",可能含有"lucene"的文檔,使用查詢:
          +jakarta apache

          NOT
          NOT操作符排除那些含有NOT符號(hào)后面項(xiàng)的文檔。這和集合的差運(yùn)算相同。符號(hào)!可以代替

          符號(hào)NOT。
          搜索含有"jakarta apache",但是不含有"jakarta lucene"的文檔,使用查詢:
          "jakarta apache" NOT "jakarta lucene"
          注意:NOT操作符不能單獨(dú)與項(xiàng)使用構(gòu)成查詢。例如,以下的查詢查不到任何結(jié)果:
          NOT "jakarta apache"

          -
          "-"操作符或者禁止操作符排除含有"-"后面的相似項(xiàng)的文檔。
          搜索含有"jakarta apache",但不是"jakarta lucene",使用查詢:
          "jakarta apache" -"jakarta lucene"

          分組(Grouping)
          Lucene支持使用圓括號(hào)來組合字句形成子查詢。這對(duì)于想控制查詢布爾邏輯的人十分有用


          搜索含有"jakarta"或者"apache",同時(shí)含有"website"的文檔,使用查詢:
          (jakarta OR apache) AND website
          這樣就消除了歧義,保證website必須存在,jakarta和apache中之一也存在。
          轉(zhuǎn)義特殊字符(Escaping Special Characters)
          Lucene支持轉(zhuǎn)義特殊字符,因?yàn)樘厥庾址遣樵冋Z法用到的。現(xiàn)在,特殊字符包括
          + - && || ! ( ) { } [ ] ^ " ~ * ? : \
          轉(zhuǎn)義特殊字符只需在字符前加上符號(hào)\,例如搜索(1+1):2,使用查詢
          \(1\+1\)\:2??
          (李宇翻譯,來自Lucene的幫助文檔)上面這段看了之后很有幫助,解除了使用中的不少

          疑惑,謝謝翻譯者,同時(shí)應(yīng)該看到,有的時(shí)候詳細(xì)查看使用幫助文檔是非常有用的。
          ------------------------------------------------------------------------------
          索引文件格式

          本文定義了Lucene(版本1.3)用到的索引文件的格式。
          Jakarta Lucene是用Java寫成的,同時(shí)有很多團(tuán)體正在默默的用其他的程序語言來改寫它

          。如果這些新的版本想和Jakarta Lucene兼容,就需要一個(gè)與具體語言無關(guān)的Lucene索引

          文件格式。本文正是試圖提供一個(gè)完整的與語言無關(guān)的Jakarta Lucene 1.3索引文件格式

          的規(guī)格定義。
          隨著Lucene不斷發(fā)展,本文也應(yīng)該更新。不同語言寫成的Lucene實(shí)現(xiàn)版本應(yīng)當(dāng)盡力遵守文

          件格式,也必須產(chǎn)生本文的新版本。
          本文同時(shí)提供兼容性批注,描述文件格式上與前一版本不同的地方。

          定義
          Lucene中最基礎(chǔ)的概念是索引(index),文檔(document),域(field)和項(xiàng)(term)


          索引包含了一個(gè)文檔的序列。
          · 文檔是一些域的序列。
          · 域是一些項(xiàng)的序列。
          · 項(xiàng)就是一個(gè)字串。
          存在于不同域中的同一個(gè)字串被認(rèn)為是不同的項(xiàng)。因此項(xiàng)實(shí)際是用一對(duì)字串表示的,第一

          個(gè)字串是域名,第二個(gè)是域中的字串。

          倒排索引
          為了使得基于項(xiàng)的搜索更有效率,索引中項(xiàng)是靜態(tài)存儲(chǔ)的。Lucene的索引屬于索引方式中

          的倒排索引,因?yàn)閷?duì)于一個(gè)項(xiàng)這種索引可以列出包含它的文檔。這剛好是文檔與項(xiàng)自然聯(lián)

          系的倒置。

          域的類型
          Lucene中,域的文本可能以逐字的非倒排的方式存儲(chǔ)在索引中。而倒排過的域稱為被索引

          過了。域也可能同時(shí)被存儲(chǔ)和被索引。
          域的文本可能被分解許多項(xiàng)目而被索引,或者就被用作一個(gè)項(xiàng)目而被索引。大多數(shù)的域是

          被分解過的,但是有些時(shí)候某些標(biāo)識(shí)符域被當(dāng)做一個(gè)項(xiàng)目索引是很有用的。

          段(Segment)
          Lucene索引可能由多個(gè)子索引組成,這些子索引成為段。每一段都是完整獨(dú)立的索引,能

          被搜索。索引是這樣作成的:
          1. 為新加入的文檔創(chuàng)建新段。
          2. 合并已經(jīng)存在的段。
          搜索時(shí)需要涉及到多個(gè)段和/或者多個(gè)索引,每一個(gè)索引又可能由一些段組成。

          文檔號(hào)(Document Number)
          內(nèi)部的來說,Lucene用一個(gè)整形(interger)的文檔號(hào)來指示文檔。第一個(gè)被加入到索引

          中的文檔就是0號(hào),順序加入的文檔將得到一個(gè)由前一個(gè)號(hào)碼遞增而來的號(hào)碼。
          注意文檔號(hào)是可能改變的,所以在Lucene外部存儲(chǔ)這些號(hào)碼時(shí)必須小心。特別的,號(hào)碼的

          改變的情況如下:
          · 只有段內(nèi)的號(hào)碼是相同的,不同段之間不同,因而在一個(gè)比段廣泛的上下文環(huán)境中使用

          這些號(hào)碼時(shí),就必須改變它們。標(biāo)準(zhǔn)的技術(shù)是根據(jù)每一段號(hào)碼多少為每一段分配一個(gè)段號(hào)

          。將段內(nèi)文檔號(hào)轉(zhuǎn)換到段外時(shí),加上段號(hào)。將某段外的文檔號(hào)轉(zhuǎn)換到段內(nèi)時(shí),根據(jù)每段中

          可能的轉(zhuǎn)換后號(hào)碼范圍來判斷文檔屬于那一段,并減調(diào)這一段的段號(hào)。例如有兩個(gè)含5個(gè)文

          檔的段合并,那么第一段的段號(hào)就是0,第二段段號(hào)5。第二段中的第三個(gè)文檔,在段外的

          號(hào)碼就是8。
          · 文檔刪除后,連續(xù)的號(hào)碼就出現(xiàn)了間斷。這可以通過合并索引來解決,段合并時(shí)刪除的

          文檔相應(yīng)也刪掉了,新合并而成的段并沒有號(hào)碼間斷。

          緒論
          索引段維護(hù)著以下的信息:
          · 域集合。包含了索引中用到的所有的域。
          · 域值存儲(chǔ)表。每一個(gè)文檔都含有一個(gè)“屬性-值”對(duì)的列表,屬性即為域名。這個(gè)列表

          用來存儲(chǔ)文檔的一些附加信息,如標(biāo)題,url或者訪問數(shù)據(jù)庫的一個(gè)ID。在搜索時(shí)存儲(chǔ)域的

          集合可以被返回。這個(gè)表以文檔號(hào)標(biāo)識(shí)。
          · 項(xiàng)字典。這個(gè)字典含有所有文檔的所有域中使用過的的項(xiàng),同時(shí)含有使用過它的文檔的

          文檔號(hào),以及指向使用頻數(shù)信息和位置信息的指針。
          · 項(xiàng)頻數(shù)信息。對(duì)于項(xiàng)字典中的每個(gè)項(xiàng),這些信息包含含有這個(gè)項(xiàng)的文檔的總數(shù),以及每

          個(gè)文檔中使用的次數(shù)。
          · 項(xiàng)位置信息。對(duì)于項(xiàng)字典中的每個(gè)項(xiàng),都存有在每個(gè)文檔中出現(xiàn)的各個(gè)位置。
          · Normalization factors. For each field in each document, a value is stored

          that is multiplied into the score for hits on that field. 標(biāo)準(zhǔn)化因子。對(duì)于文檔

          中的每一個(gè)域,存有一個(gè)值,用來以后乘以這個(gè)這個(gè)域的命中數(shù)(hits)。
          · 被刪除的文檔信息。這是一個(gè)可選文件,用來表明那些文檔已經(jīng)刪除了。
          接下來的各部分部分詳細(xì)描述這些信息。

          文件的命名(File Naming)
          同屬于一個(gè)段的文件擁有相同的文件名,不同的擴(kuò)展名。擴(kuò)展名由以下討論的各種文件格

          式確定。
          一般來說,一個(gè)索引存放一個(gè)目錄,其所有段都存放在這個(gè)目錄里,盡管我們不要求您這

          樣做。

          基本數(shù)據(jù)類型(Primitive Types)

          Byte
          最基本的數(shù)據(jù)類型就是字節(jié)(byte,8位)。文件就是按字節(jié)順序訪問的。其它的一些數(shù)據(jù)

          類型也定義為字節(jié)的序列,文件的格式具有字節(jié)意義上的獨(dú)立性。

          UInt32
          32位無符號(hào)整數(shù),由四個(gè)字節(jié)組成,高位優(yōu)先。

          UInt32 --> <Byte>4
          Uint64
          64位無符號(hào)整數(shù),由八字節(jié)組成,高位優(yōu)先。

          UInt64 --> <Byte>8
          VInt
          可變長的正整數(shù)類型,每字節(jié)的最高位表明還剩多少字節(jié)。每字節(jié)的低七位表明整數(shù)的值

          。因此單字節(jié)的值從0到127,兩字節(jié)值從128到16,383,等等。

          VInt 編碼示例
          Value
          First byte
          Second byte
          Third byte

          0
          00000000
          1
          00000001
          2
          00000010
          ...
          127
          01111111
          128
          10000000
          00000001
          129
          10000001
          00000001
          130
          10000010
          00000001
          ...
          16,383
          11111111
          01111111
          16,384
          10000000
          10000000
          00000001
          16,385
          10000001
          10000000
          00000001
          ...

          這種編碼提供了一種在高效率解碼時(shí)壓縮數(shù)據(jù)的方法。

          Chars
          Lucene輸出UNICODE字符序列,使用標(biāo)準(zhǔn)UTF-8編碼。

          String
          Lucene輸出由VINT和字符串組成的字串,VINT表示字串長,字符串緊接其后。
          String --> VInt, Chars

          索引包含的文件(Per-Index Files)
          這部分介紹每個(gè)索引包含的文件。

          Segments文件
          索引中活動(dòng)的段存儲(chǔ)在Segments文件中。每個(gè)索引只能含有一個(gè)這樣的文件,名

          為"segments".這個(gè)文件依次列出每個(gè)段的名字和每個(gè)段的大小。
          Segments --> SegCount, <SegName, SegSize>SegCount
          SegCount, SegSize --> UInt32
          SegName --> String
          SegName表示該segment的名字,同時(shí)作為索引其他文件的前綴。
          SegSize是段索引中含有的文檔數(shù)。

          Lock文件
          有一些文件用來表示另一個(gè)進(jìn)程在使用索引。
          · 如果存在"commit.lock"文件,表示有進(jìn)程在寫"segments"文件和刪除無用的段索引文

          件,或者表示有進(jìn)程在讀"segments"文件和打開某些段的文件。在一個(gè)進(jìn)程在讀

          取"segments"文件段信息后,還沒來得及打開所有該段的文件前,這個(gè)Lock文件可以防止

          另一個(gè)進(jìn)程刪除這些文件。
          · 如果存在"index.lock"文件,表示有進(jìn)程在向索引中加入文檔,或者是從索引中刪除文

          檔。這個(gè)文件防止很多文件同時(shí)修改一個(gè)索引。

          Deleteable文件
          名為"deletetable"的文件包含了索引不再使用的文件的名字,這些文件可能并沒有被實(shí)際

          的刪除。這種情況只存在與Win32平臺(tái)下,因?yàn)閃in32下文件仍打開時(shí)并不能刪除。
          Deleteable --> DelableCount, <DelableName>DelableCount
          DelableCount --> UInt32
          DelableName --> String

          段包含的文件(Per-Segment Files)
          剩下的文件是每段中包含的文件,因此由后綴來區(qū)分。
          域(Field)
          域集合信息(Field Info)
          所有域名都存儲(chǔ)在這個(gè)文件的域集合信息中,這個(gè)文件以后綴.fnm結(jié)尾。
          FieldInfos (.fnm) --> FieldsCount, <FieldName, FieldBits>FieldsCount
          FieldsCount --> VInt
          FieldName --> String
          FieldBits --> Byte
          目前情況下,F(xiàn)ieldBits只有使用低位,對(duì)于已索引的域值為1,對(duì)未索引的域值為0。
          文件中的域根據(jù)它們的次序編號(hào)。因此域0是文件中的第一個(gè)域,域1是接下來的,等等。

          這個(gè)和文檔號(hào)的編號(hào)方式相同。
          域值存儲(chǔ)表(Stored Fields)
          域值存儲(chǔ)表使用兩個(gè)文件表示:

          1. 域索引(.fdx文件)。
          如下,對(duì)于每個(gè)文檔這個(gè)文件包含指向域值的指針:
          FieldIndex (.fdx) --> <FieldValuesPosition>SegSize
          FieldValuesPosition --> Uint64
          FieldValuesPosition指示的是某一文檔的某域的域值在域值文件中的位置。因?yàn)橛蛑滴募?/p>

          含有定長的數(shù)據(jù)信息,因而很容易隨機(jī)訪問。在域值文件中,文檔n的域值信息就存在n*8

          位置處(The position of document n's field data is the Uint64 at n*8 in this

          file.)。

          2. 域值(.fdt文件)。
          如下,每個(gè)文檔的域值信息包含:
          FieldData (.fdt) --> <DocFieldData>SegSize
          DocFieldData --> FieldCount, <FieldNum, Bits, Value>FieldCount
          FieldCount --> VInt
          FieldNum --> VInt
          Bits --> Byte
          Value --> String
          目前情況下,Bits只有低位被使用,值為1表示域名被分解過,值為0表示未分解過。

          項(xiàng)字典(Term Dictionary)
          項(xiàng)字典用以下兩個(gè)文件表示:
          1. 項(xiàng)信息(.tis文件)。
          TermInfoFile (.tis)--> TermCount, TermInfos
          TermCount --> UInt32
          TermInfos --> <TermInfo>TermCount
          TermInfo --> <Term, DocFreq, FreqDelta, ProxDelta>
          Term --> <PrefixLength, Suffix, FieldNum>
          Suffix --> String
          PrefixLength, DocFreq, FreqDelta, ProxDelta
          --> VInt
          項(xiàng)信息按項(xiàng)排序。項(xiàng)信息排序時(shí)先按項(xiàng)所屬的域的文字順序排序,然后按照項(xiàng)的字串的文

          字順序排序。
          項(xiàng)的字前綴往往是共同的,與字的后綴組成字。PrefixLength變量就是表示與前一項(xiàng)相同

          的前綴的字?jǐn)?shù)。因此,如果前一個(gè)項(xiàng)的字是"bone",后一個(gè)是"boy"的話,PrefixLength值

          為2,Suffix值為"y"。

          FieldNum指明了項(xiàng)屬于的域號(hào),而域名存儲(chǔ)在.fdt文件中。
          DocFreg表示的是含有該項(xiàng)的文檔的數(shù)量。
          FreqDelta指明了項(xiàng)所屬TermFreq變量在.frq文件中的位置。詳細(xì)的說,就是指相對(duì)于前一

          個(gè)項(xiàng)的數(shù)據(jù)的位置偏移量(或者是0,表示文件中第一個(gè)項(xiàng))。
          ProxDelta指明了項(xiàng)所屬的TermPosition變量在.prx文件中的位置。詳細(xì)的說,就是指相對(duì)

          于前一個(gè)項(xiàng)的數(shù)據(jù)的位置偏移量(或者是0,表示文件中第一個(gè)項(xiàng))。

          2. 項(xiàng)信息索引(.tii文件)。
          每個(gè)項(xiàng)信息索引文件包含.tis文件中的128個(gè)條目,依照條目在.tis文件中的順序。這樣設(shè)

          計(jì)是為了一次將索引信息讀入內(nèi)存能,然后使用它來隨機(jī)的訪問.tis文件。
          這個(gè)文件的結(jié)構(gòu)和.tis文件非常類似,只在每個(gè)條目記錄上增加了一個(gè)變量IndexDelta。
          TermInfoIndex (.tii)--> IndexTermCount, TermIndices
          IndexTermCount --> UInt32
          TermIndices --> <TermInfo, IndexDelta>IndexTermCount
          IndexDelta --> VInt
          IndexDelta表示該項(xiàng)的TermInfo變量值在.tis文件中的位置。詳細(xì)的講,就是指相對(duì)于前

          一個(gè)條目的偏移量(或者是0,對(duì)于文件中第一個(gè)項(xiàng))。

          項(xiàng)頻數(shù)(Frequencies)
          .frq文件包含每一項(xiàng)的文檔的列表,還有該項(xiàng)在對(duì)應(yīng)文檔中出現(xiàn)的頻數(shù)。
          FreqFile (.frq) --> <TermFreqs>TermCount
          TermFreqs --> <TermFreq>DocFreq
          TermFreq --> DocDelta, Freq?
          DocDelta,Freq --> VInt
          TermFreqs序列按照項(xiàng)來排序(依據(jù)于.tis文件中的項(xiàng),即項(xiàng)是隱含存在的)。
          TermFreq元組按照文檔號(hào)升序排列。
          DocDelta決定了文檔號(hào)和頻數(shù)。詳細(xì)的說,DocDelta/2表示相對(duì)于前一文檔號(hào)的偏移量(

          或者是0,表示這是TermFreqs里面的第一項(xiàng))。當(dāng)DocDelta是奇數(shù)時(shí)表示在該文檔中頻數(shù)

          為1,當(dāng)DocDelta是偶數(shù)時(shí),另一個(gè)VInt(Freq)就表示在該文檔中出現(xiàn)的頻數(shù)。
          例如,假設(shè)某一項(xiàng)在文檔7中出現(xiàn)一次,在文檔11中出現(xiàn)了3次,在TermFreqs中就存在如下

          的VInts序列: 15, 22, 3

          項(xiàng)位置(Position)
          .prx文件包含了某文檔中某項(xiàng)出現(xiàn)的位置信息的列表。
          ProxFile (.prx) --> <TermPositions>TermCount
          TermPositions --> <Positions>DocFreq
          Positions --> <PositionDelta>Freq
          PositionDelta --> VInt
          TermPositions按照項(xiàng)來排序(依據(jù)于.tis文件中的項(xiàng),即項(xiàng)是隱含存在的)。
          Positions元組按照文檔號(hào)升序排列。
          PositionDelta是相對(duì)于前一個(gè)出現(xiàn)位置的偏移位置(或者為0,表示這是第一次在這個(gè)文

          檔中出現(xiàn))。
          例如,假設(shè)某一項(xiàng)在某文檔第4項(xiàng)出現(xiàn),在另一個(gè)文檔中第5項(xiàng)和第9項(xiàng)出現(xiàn),將存在如下的

          VInt序列: 4, 5, 4

          標(biāo)準(zhǔn)化因子(Normalization Factor)
          .nrm文件包含了每個(gè)文檔的標(biāo)準(zhǔn)化因子,標(biāo)準(zhǔn)化因子用來以后乘以這個(gè)這個(gè)域的命中數(shù)。
          Norms (.nrm) --> <Byte>SegSize
          每個(gè)字節(jié)記錄一個(gè)浮點(diǎn)數(shù)。位0-2包含了3位的尾數(shù)部分,位3-8包含了5位的指數(shù)部分。
          按如下規(guī)則可將這些字節(jié)轉(zhuǎn)換為IEEE標(biāo)準(zhǔn)單精度浮點(diǎn)數(shù):
          1. 如果該字節(jié)是0,就是浮點(diǎn)0;
          2. 否則,設(shè)置新浮點(diǎn)數(shù)的標(biāo)志位為0;
          3. 將字節(jié)中的指數(shù)加上48后作為新的浮點(diǎn)數(shù)的指數(shù);
          4. 將字節(jié)中的尾數(shù)映射到新浮點(diǎn)數(shù)尾數(shù)的高3位;并且
          5. 設(shè)置新浮點(diǎn)數(shù)尾數(shù)的低21位為0。

          被刪除的文檔(Deleted Document)
          .del文件是可選的,只有在某段中存在刪除操作后才存在:
          Deletions (.del) --> ByteCount,BitCount,Bits
          ByteSize,BitCount --> Uint32
          Bits --> <Byte>ByteCount
          ByteCount表示的是Bits列表中Byte的數(shù)量。典型的,它等于(SegSize/8)+1。
          BitCount表示Bits列表中多少個(gè)已經(jīng)被設(shè)置過了。
          Bits列表包含了一些位(bit),順序表示一個(gè)文檔。當(dāng)對(duì)應(yīng)于文檔號(hào)的位被設(shè)置了,就標(biāo)

          志著這個(gè)文檔已經(jīng)被刪除了。位的順序是從低到高。因此,如果Bits包含兩個(gè)字節(jié),0x00

          和0x02,那么表示文檔9已經(jīng)刪除了。

          局限性(Limitations)
          在以上的文件格式中,好幾處都有限制項(xiàng)和文檔的最大個(gè)數(shù)為32位數(shù)的極限,即接近于40

          億。今天看來,這不會(huì)造成問題,但是,長遠(yuǎn)的看,可能造成問題。因此,這些極限應(yīng)該

          或者換為UInt64類型的值,或者更好的,換為VInt類型的值(VInt值沒有上限)。
          有兩處地方的代碼要求必須是定長的值,他們是:
          1. FieldValuesPosition變量(存儲(chǔ)于域索引文件中,.fdx文件)。它已經(jīng)是一個(gè)UInt64

          型,所以不會(huì)有問題。
          2. TermCount變量(存儲(chǔ)于項(xiàng)信息文件中,.tis文件)。這是最后輸出到文件中的,但是

          最先被讀取,因此是存儲(chǔ)于文件的最前端 。索引代碼先在這里寫入一個(gè)0值,然后在其他

          文件輸出完畢后覆蓋這個(gè)值。所以無論它存儲(chǔ)在什么地方,它都必須是一個(gè)定長的值,它

          應(yīng)該被變成UInt64型。
          除此之外,所有的UInt值都可以換成VInt型以去掉限制
          ------------------------------------------------------------------------------

          ---------
          下面是lucene組成結(jié)構(gòu)中的類說明:
          org.apache.Lucene.search/ 搜索入口
          org.apache.Lucene.index/ 索引入口
          org.apache.Lucene.analysis/ 語言分析器
          org.apache.Lucene.queryParser/ 查詢分析器
          org.apache.Lucene.document/ 存儲(chǔ)結(jié)構(gòu)
          org.apache.Lucene.store/? 底層IO/存儲(chǔ)結(jié)構(gòu)
          org.apache.Lucene.util/ 一些公用的數(shù)據(jù)結(jié)構(gòu)

          域存儲(chǔ)字段規(guī)則
          方法 切詞 索引 存儲(chǔ) 用途
          Field.Text(String name, String value) 切分詞索引并存儲(chǔ),比如:標(biāo)題,內(nèi)容字段
          Field.Text(String name, Reader value)? 切分詞索引不存儲(chǔ),比如:META信息,
          不用于返回顯示,但需要進(jìn)行檢索內(nèi)容
          Field.Keyword(String name, String value)? 不切分索引并存儲(chǔ),比如:日期字段
          Field.UnIndexed(String name, String value)? 不索引,只存儲(chǔ),比如:文件路徑
          Field.UnStored(String name, String value)? 只全文索引,不存儲(chǔ)

          建立索引的例子:
          public class IndexFiles {??
          //使用方法:: IndexFiles [索引輸出目錄] [索引的文件列表] ...??
          public static void main(String[] args) throws Exception {???
          String indexPath = args[0];??? IndexWriter writer;???
          //用指定的語言分析器構(gòu)造一個(gè)新的寫索引器(第3個(gè)參數(shù)表示是否為追加索引)???

          writer = new IndexWriter(indexPath, new SimpleAnalyzer(), false);???
          for (int i=1; i<args.length; i++) {?????
          System.out.println("Indexing file " + args[i]);?????
          InputStream is = new FileInputStream(args[i]);?????
          //構(gòu)造包含2個(gè)字段Field的Document對(duì)象?????
          //一個(gè)是路徑path字段,不索引,只存儲(chǔ)?????
          //一個(gè)是內(nèi)容body字段,進(jìn)行全文索引,并存儲(chǔ)?????
          Document doc = new Document();?????
          doc.add(Field.UnIndexed("path", args[i]));?????
          doc.add(Field.Text("body", (Reader) new InputStreamReader(is)));?????
          //將文檔寫入索引????
          ?writer.addDocument(doc);?????
          is.close();??? };???
          //關(guān)閉寫索引器???
          writer.close();? }
          }
          索引過程中可以看到:

          語言分析器提供了抽象的接口,因此語言分析(Analyser)是可以定制的,雖然lucene缺省

          提供了2個(gè)比較通用的分析器SimpleAnalyser和StandardAnalyser,這2個(gè)分析器缺省都不

          支持中文,所以要加入對(duì)中文語言的切分規(guī)則,需要修改這2個(gè)分析器。
          Lucene并沒有規(guī)定數(shù)據(jù)源的格式,而只提供了一個(gè)通用的結(jié)構(gòu)(Document對(duì)象)來接受索

          引的輸入,因此輸入的數(shù)據(jù)源可以是:數(shù)據(jù)庫,WORD文檔,PDF文檔,HTML文檔……只要能

          夠設(shè)計(jì)相應(yīng)的解析轉(zhuǎn)換器將數(shù)據(jù)源構(gòu)造成成Docuement對(duì)象即可進(jìn)行索引。
          對(duì)于大批量的數(shù)據(jù)索引,還可以通過調(diào)整IndexerWrite的文件合并頻率屬性(mergeFactor

          )來提高批量索引的效率。
          檢索過程和結(jié)果顯示:

          搜索結(jié)果返回的是Hits對(duì)象,可以通過它再訪問Document==>Field中的內(nèi)容。

          假設(shè)根據(jù)body字段進(jìn)行全文檢索,可以將查詢結(jié)果的path字段和相應(yīng)查詢的匹配度(score)

          打印出來,

          public class Search {??
          public static void main(String[] args) throws Exception {???
          String indexPath = args[0], queryString = args[1];???
          //指向索引目錄的搜索器???
          Searcher searcher = new IndexSearcher(indexPath);???
          //查詢解析器:使用和索引同樣的語言分析器???
          Query query = QueryParser.parse(queryString, "body",???????????????????????????

          ?? new SimpleAnalyzer());???
          //搜索結(jié)果使用Hits存儲(chǔ)???
          Hits hits = searcher.search(query);???
          //通過hits可以訪問到相應(yīng)字段的數(shù)據(jù)和查詢的匹配度???
          for (int i=0; i<hits.length(); i++) {?????
          System.out.println(hits.doc(i).get("path") + "; Score: " +?????????????????????

          ??? hits.score(i));??? };? }
          }
          添加修改刪除指定記錄(Document)

          Lucene提供了索引的擴(kuò)展機(jī)制,因此索引的動(dòng)態(tài)擴(kuò)展應(yīng)該是沒有問題的,而指定記錄的修

          改也似乎只能通過記錄的刪除,然后重新加入實(shí)現(xiàn)。如何刪除指定的記錄呢?刪除的方法

          也很簡單,只是需要在索引時(shí)根據(jù)數(shù)據(jù)源中的記錄ID專門另建索引,然后利用

          IndexReader.delete(Termterm)方法通過這個(gè)記錄ID刪除相應(yīng)的Document。

          根據(jù)某個(gè)字段值的排序功能
          根據(jù)某個(gè)字段值的排序功能

          lucene缺省是按照自己的相關(guān)度算法(score)進(jìn)行結(jié)果排序的,但能夠根據(jù)其他字段進(jìn)行

          結(jié)果排序是一個(gè)在LUCENE的開發(fā)郵件列表中經(jīng)常提到的問題,很多原先基于數(shù)據(jù)庫應(yīng)用都

          需要除了基于匹配度(score)以外的排序功能。而從全文檢索的原理我們可以了解到,任

          何不基于索引的搜索過程效率都會(huì)導(dǎo)致效率非常的低,如果基于其他字段的排序需要在搜

          索過程中訪問存儲(chǔ)字段,速度回大大降低,因此非常是不可取的。

          但這里也有一個(gè)折中的解決方法:在搜索過程中能夠影響排序結(jié)果的只有索引中已經(jīng)存儲(chǔ)

          的docID和score這2個(gè)參數(shù),所以,基于score以外的排序,其實(shí)可以通過將數(shù)據(jù)源預(yù)先排

          好序,然后根據(jù)docID進(jìn)行排序來實(shí)現(xiàn)。這樣就避免了在LUCENE搜索結(jié)果外對(duì)結(jié)果再次進(jìn)行

          排序和在搜索過程中訪問不在索引中的某個(gè)字段值。

          這里需要修改的是IndexSearcher中的HitCollector過程:

          ... scorer.score(new HitCollector() {?
          private float minScore = 0.0f;?
          public final void collect(int doc, float score) {??
          if (score > 0.0f &&???? // ignore zeroed buckets??????

          (bits==null || bits.get(doc))) {?? // skip docs not in bits????

          totalHits[0]++;???? if (score >= minScore) {????????????? /* 原先:Lucene將

          docID和相應(yīng)的匹配度score例入結(jié)果命中列表中:??????? * hq.put(new ScoreDoc

          (doc, score));?? // update hit queue?????????????? * 如果用doc 或 1/doc 代替

          score,就實(shí)現(xiàn)了根據(jù)docID順排或逆排?????????????? * 假設(shè)數(shù)據(jù)源索引時(shí)已經(jīng)按照某個(gè)

          字段排好了序,而結(jié)果根據(jù)docID排序也就實(shí)現(xiàn)了?????????????? * 針對(duì)某個(gè)字段的排序

          ,甚至可以實(shí)現(xiàn)更復(fù)雜的score和docID的擬合。?????????????? */?????????????

          hq.put(new ScoreDoc(doc, (float) 1/doc )); ??????
          if (hq.size() > nDocs) {??? // if hit queue overfull??

          hq.pop();???? // remove lowest in hit queue??

          minScore = ((ScoreDoc)hq.top()).score; // reset minScore?????? }???? }?

          ? }?}????? }, reader.maxDoc());

          Lucene面向全文檢索的優(yōu)化在于首次索引檢索后,并不把所有的記錄(Document)具體內(nèi)

          容讀取出來,而起只將所有結(jié)果中匹配度最高的頭100條結(jié)果(TopDocs)的ID放到結(jié)果集

          緩存中并返回,這里可以比較一下數(shù)據(jù)庫檢索:如果是一個(gè)10,000條的數(shù)據(jù)庫檢索結(jié)果集

          ,數(shù)據(jù)庫是一定要把所有記錄內(nèi)容都取得以后再開始返回給應(yīng)用結(jié)果集的。所以即使檢索

          匹配總數(shù)很多,Lucene的結(jié)果集占用的內(nèi)存空間也不會(huì)很多。對(duì)于一般的模糊檢索應(yīng)用是

          用不到這么多的結(jié)果的,頭100條已經(jīng)可以滿足90%以上的檢索需求。

          如果首批緩存結(jié)果數(shù)用完后還要讀取更后面的結(jié)果時(shí)Searcher會(huì)再次檢索并生成一個(gè)上次

          的搜索緩存數(shù)大1倍的緩存,并再重新向后抓取。所以如果構(gòu)造一個(gè)Searcher去查1-120條

          結(jié)果,Searcher其實(shí)是進(jìn)行了2次搜索過程:頭100條取完后,緩存結(jié)果用完,Searcher重

          新檢索再構(gòu)造一個(gè)200條的結(jié)果緩存,依此類推,400條緩存,800條緩存。由于每次

          Searcher對(duì)象消失后,這些緩存也訪問那不到了,你有可能想將結(jié)果記錄緩存下來,緩存

          數(shù)盡量保證在100以下以充分利用首次的結(jié)果緩存,不讓Lucene浪費(fèi)多次檢索,而且可以分

          級(jí)進(jìn)行結(jié)果緩存。

          Lucene的另外一個(gè)特點(diǎn)是在收集結(jié)果的過程中將匹配度低的結(jié)果自動(dòng)過濾掉了。這也是和

          數(shù)據(jù)庫應(yīng)用需要將搜索的結(jié)果全部返回不同之處。

          posted @ 2006-11-08 14:58 Lansing 閱讀(1368) | 評(píng)論 (0)編輯 收藏

          Eclipse及其插件介紹和下載- -

          TagEclipse ?? 插件 ?? ??????????????????????????????????????

          0.Eclipse下載
          EMF,GEF - Graphical Editor Framework,UML2,VE - Visual Editor都在這里下載
          http://www.eclipse.org/downloads/index.php
          ?
          0.5.lomboz J2EE插件,開發(fā)JSP,EJB
          http://forge.objectweb.org/projects/lomboz
          1.MyEclipse J2EE開發(fā)插件,支持SERVLET/JSP/EJB/數(shù)據(jù)庫操縱等
          http://www.myeclipseide.com
          ?
          2.Properties Editor? 編輯java的屬性文件,并可以自動(dòng)存盤為Unicode格式
          http://propedit.sourceforge.jp/index_en.html
          ?
          3.Colorer Take? 為上百種類型的文件按語法著色
          http://colorer.sourceforge.net/
          ?
          4.XMLBuddy 編輯xml文件
          http://www.xmlbuddy.com
          ?
          5.Code Folding? 加入多種代碼折疊功能(比eclipse自帶的更多)
          http://www.coffee-bytes.com/servlet/PlatformSupport
          ?
          6.Easy Explorer? 從eclipse中訪問選定文件、目錄所在的文件夾
          http://easystruts.sourceforge.net/
          ?
          7.Fat Jar 打包插件,可以方便的完成各種打包任務(wù),可以包含外部的包等
          http://fjep.sourceforge.net/
          ?
          8.RegEx Test 測試正則表達(dá)式
          http://brosinski.com/stephan/archives/000028.php
          ?
          9.JasperAssistant 報(bào)表插件(強(qiáng),要錢的)
          http://www.jasperassistant.com/
          ?
          10.Jigloo GUI Builder JAVA的GUI編輯插件
          http://cloudgarden.com/jigloo/
          ?
          11.Profiler 性能跟蹤、測量工具,能跟蹤、測量BS程序
          http://sourceforge.net/projects/eclipsecolorer/
          ?
          12.AdvanQas 提供對(duì)if/else等條件語句的提示和快捷幫助(自動(dòng)更改結(jié)構(gòu)等)
          http://eclipsecolorer.sourceforge.net/advanqas/index.html
          ?
          13.Log4E Log4j插件,提供各種和Log4j相關(guān)的任務(wù),如為方法、類添加一個(gè)logger等
          http://log4e.jayefem.de/index.php/Main_Page
          ?
          14.VSSPlugin VSS插件
          http://sourceforge.net/projects/vssplugin
          ?
          15.Implementors 提供跳轉(zhuǎn)到一個(gè)方法的實(shí)現(xiàn)類,而不是接中的功能(實(shí)用!)
          http://eclipse-tools.sourceforge.net/implementors/
          ?
          16.Call Hierarchy 顯示一個(gè)方法的調(diào)用層次(被哪些方法調(diào),調(diào)了哪些方法)
          http://eclipse-tools.sourceforge.net/call-hierarchy/index.html
          ?
          17.EclipseTidy 檢查和格式化HTML/XML文件
          http://eclipsetidy.sourceforge.net/
          ?
          18.Checkclipse 檢查代碼的風(fēng)格、寫法是否符合規(guī)范
          http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm
          ?
          19.Hibernate Synchronizer Hibernate插件,自動(dòng)映射等
          http://www.binamics.com/hibernatesync/
          ?
          20.VeloEclipse? Velocity插件
          http://propsorter.sourceforge.net/
          ?
          21.EditorList 方便的列出所有打開的Editor
          http://editorlist.sourceforge.net/
          ?
          22.MemoryManager 內(nèi)存占用率的監(jiān)視
          http://cloudgarden.com/memorymanager/
          ?
          23.swt-designer java的GUI插件
          http://www.swt-designer.com/
          ?
          24.TomcatPlugin 支持Tomcat插件
          http://www.sysdeo.com/eclipse/tomcatPlugin.html
          ?
          25.XML Viewer
          http://tabaquismo.freehosting.net/ignacio/eclipse/xmlview/index.html
          ?
          26.quantum 數(shù)據(jù)庫插件
          http://quantum.sourceforge.net/
          ?
          27.Dbedit 數(shù)據(jù)庫插件
          http://sourceforge.net/projects/dbedit
          ?
          28.clay.core 可視化的數(shù)據(jù)庫插件
          http://www.azzurri.jp/en/software/index.jsp
          http://www.azzurri.jp/eclipse/plugins
          ?
          29.hiberclipse hibernate插件
          http://hiberclipse.sourceforge.net
          http://www.binamics.com/hibernatesync
          ?
          30.struts-console Struts插件
          http://www.jamesholmes.com/struts/console/
          ?
          31.easystruts Struts插件
          http://easystruts.sourceforge.net
          ?
          32.veloedit Velocity插件
          http://veloedit.sourceforge.net/
          ?
          33.jalopy 代碼整理插件
          http://jalopy.sourceforge.net/
          ?
          34.JDepend 包關(guān)系分析
          http://andrei.gmxhome.de/jdepend4eclipse/links.html
          ?
          35.Spring IDE Spring插件
          http://springide-eclip.sourceforge.net/updatesite/
          ?
          36.doclipse 可以產(chǎn)生xdoclet 的代碼提示
          http://beust.com/doclipse/

          posted @ 2006-09-21 19:17 Lansing 閱讀(316) | 評(píng)論 (0)編輯 收藏

          Struts常見異常信息和解決方法

          以下所說的struts-config.xml和ApplicationResources.properties等文件名是缺省時(shí)使用的,如果你使用了多模塊,或指定了不同的資源文件名稱,這些名字要做相應(yīng)的修改。

          1、“No bean found under attribute key XXX”
          在struts-config.xml里定義了一個(gè)ActionForm,但type屬性指定的類不存在,type屬性的值應(yīng)該是Form類的全名。或者是,在Action的定義中,name或attribute屬性指定的ActionForm不存在。

          2、“Cannot find bean?XXX in any scope”
          在Action里一般會(huì)request.setAttribute()一些對(duì)象,然后在轉(zhuǎn)向的jsp文件里(用tag或request.getAttribute()方法)得到這些對(duì)象并顯示出來。這個(gè)異常是說jsp要得到一個(gè)對(duì)象,但前面的Action里并沒有將對(duì)象設(shè)置到request(也可以是session、servletContext)里。
          可能是名字錯(cuò)了,請檢查jsp里的tag的一般是name屬性,或getAttribute()方法的參數(shù)值;或者是Action邏輯有問題沒有執(zhí)行setAttribute()方法就先轉(zhuǎn)向了。
          還有另外一個(gè)可能,純粹是jsp文件的問題,例如<logic:iterate>會(huì)指定一個(gè)id值,然后在循環(huán)里<bean:write>使用這個(gè)值作為name的值,如果這兩個(gè)值不同,也會(huì)出現(xiàn)此異常。(都是一個(gè)道理,request里沒有對(duì)應(yīng)的對(duì)象。)

          3、“Missing message for key "XXX"”
          缺少所需的資源,檢查ApplicationResources.properties文件里是否有jsp文件里需要的資源,例如:

          < bean:message?key = " msg.name.prompt " />

          這行代碼會(huì)找msg.name.prompt資源,如果AppliationResources.properties里沒有這個(gè)資源就會(huì)出現(xiàn)本異常。在使用多模塊時(shí),要注意在模塊的struts-config-xxx.xml里指定要使用的資源文件名稱,否則當(dāng)然什么資源也找不到,這也是一個(gè)很容易犯的錯(cuò)誤。

          4、“No getter method for property?XXX of bean teacher”
          這條異常信息說得很明白,jsp里要取一個(gè)bean的屬性出來,但這個(gè)bean并沒有這個(gè)屬性。你應(yīng)該檢查jsp中某個(gè)標(biāo)簽的property屬性的值。例如下面代碼中的cade應(yīng)該改為code才對(duì):

          < bean:write?name = " teacher " ?property = " cade " ?filter = " true " />

          5、“Cannot find ActionMappings or ActionFormBeans collection”
          待解決。

          6、“Cannot retrieve mapping for action XXX”
          在.jsp的<form>標(biāo)簽里指定action='/XXX',但這個(gè)Action并未在struts-config.xml里設(shè)置過。

          7、HTTP Status 404 - /xxx/xxx.jsp
          Forward的path屬性指向的jsp頁面不存在,請檢查路徑和模塊,對(duì)于同一模塊中的Action轉(zhuǎn)向,path中不應(yīng)包含模塊名;模塊間轉(zhuǎn)向,記住使用contextRelative="true"。

          8、沒有任何異常信息,顯示空白頁面
          可能是Action里使用的forward與struts-config.xml里定義的forward名稱不匹配。

          9、“The element type "XXX" must be terminated by the matching end-tag "XXX".”
          這個(gè)是struts-config.xml文件的格式錯(cuò)誤,仔細(xì)檢查它是否是良構(gòu)的xml文件,關(guān)于xml文件的格式這里就不贅述了。

          10、“Servlet.init() for servlet action threw exception”
          一般出現(xiàn)這種異常在后面會(huì)顯示一個(gè)關(guān)于ActionServlet的異常堆棧信息,其中指出了異常具體出現(xiàn)在代碼的哪一行。我曾經(jīng)遇到的一次提示如下:

          java.lang.NullPointerException
          ????at?org.apache.struts.action.ActionServlet.parseModuleConfigFile(ActionServlet.java:
          1003 )
          ????at?org.apache.struts.action.ActionServlet.initModuleConfig(ActionServlet.java:
          955 )


          為解決問題,先下載struts的源碼包,然后在ActionServlet.java的第1003行插入斷點(diǎn),并對(duì)各變量進(jìn)行監(jiān)視。很丟人,我竟然把struts-config.xml文件弄丟了,因此出現(xiàn)了上面的異常,應(yīng)該是和CVS同步時(shí)不小心刪除的。

          11、“Resources not defined for Validator”
          這個(gè)是利用Validator插件做驗(yàn)證時(shí)可能出現(xiàn)的異常,這時(shí)你要檢查validation.xml文件,看里面使用的資源是否確實(shí)有定義,form的名稱是否正確,等等。

          posted @ 2006-09-19 11:34 Lansing 閱讀(338) | 評(píng)論 (0)編輯 收藏
               摘要: PowerDesigner 設(shè)計(jì)數(shù)據(jù)庫 ? ? ? ?????? 本文檔不講述如何使用 PowerDesigner ,而是講述如何將 PowerDesigner...  閱讀全文
          posted @ 2006-09-13 14:53 Lansing 閱讀(679) | 評(píng)論 (0)編輯 收藏
          Log4j由三個(gè)重要的組件構(gòu)成:日志信息的優(yōu)先級(jí),日志信息的輸出目的地,日志信息的輸出格式。日志信息的優(yōu)先級(jí)從高到低有ERROR、WARN、INFO、DEBUG,分別用來指定這條日志信息的重要程度;日志信息的輸出目的地指定了日志將打印到控制臺(tái)還是文件中;而輸出格式則控制了日志信息的顯示內(nèi)容。

            一、定義配置文件

            其實(shí)您也可以完全不使用配置文件,而是在代碼中配置Log4j環(huán)境。但是,使用配置文件將使您的應(yīng)用程序更加靈活。Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是Java特性文件(鍵=值)。下面我們介紹使用Java特性文件做為配置文件的方法:

            1.配置根Logger,其語法為:

            log4j.rootLogger = [ level ] , appenderName, appenderName, …

            其中,level 是日志記錄的優(yōu)先級(jí),分為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定義的級(jí)別。Log4j建議只使用四個(gè)級(jí)別,優(yōu)先級(jí)從高到低分別是ERROR、WARN、INFO、DEBUG。通過在這里定義的級(jí)別,您可以控制到應(yīng)用程序中相應(yīng)級(jí)別的日志信息的開關(guān)。比如在這里定義了INFO級(jí)別,則應(yīng)用程序中所有DEBUG級(jí)別的日志信息將不被打印出來。 appenderName就是指定日志信息輸出到哪個(gè)地方。您可以同時(shí)指定多個(gè)輸出目的地。

            2.配置日志信息輸出目的地Appender,其語法為:

            log4j.appender.appenderName = fully.qualified.name.of.appender.class
            log4j.appender.appenderName.option1 = value1
            …
            log4j.appender.appenderName.option = valueN

            其中,Log4j提供的appender有以下幾種:
            org.apache.log4j.ConsoleAppender(控制臺(tái)),
            org.apache.log4j.FileAppender(文件),
            org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個(gè)日志文件),
            org.apache.log4j.RollingFileAppender(文件大小到達(dá)指定尺寸的時(shí)候產(chǎn)生一個(gè)新的文件),
            org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)

            3.配置日志信息的格式(布局),其語法為:

            log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
            log4j.appender.appenderName.layout.option1 = value1
            …
            log4j.appender.appenderName.layout.option = valueN

            其中,Log4j提供的layout有以下幾種:
            org.apache.log4j.HTMLLayout(以HTML表格形式布局),
            org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
            org.apache.log4j.SimpleLayout(包含日志信息的級(jí)別和信息字符串),
            org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時(shí)間、線程、類別等等信息)

            Log4J采用類似C語言中的printf函數(shù)的打印格式格式化日志信息,打印參數(shù)如下: %m 輸出代碼中指定的消息

            %p 輸出優(yōu)先級(jí),即DEBUG,INFO,WARN,ERROR,F(xiàn)ATAL
            %r 輸出自應(yīng)用啟動(dòng)到輸出該log信息耗費(fèi)的毫秒數(shù)
            %c 輸出所屬的類目,通常就是所在類的全名
            %t 輸出產(chǎn)生該日志事件的線程名
            %n 輸出一個(gè)回車換行符,Windows平臺(tái)為“\r\n”,Unix平臺(tái)為“\n”
            %d 輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921
            %l 輸出日志事件的發(fā)生位置,包括類目名、發(fā)生的線程,以及在代碼中的行數(shù)。舉例:Testlog4.main(TestLog4.java:10)

            二、在代碼中使用Log4j

            1.得到記錄器

            使用Log4j,第一步就是獲取日志記錄器,這個(gè)記錄器將負(fù)責(zé)控制日志信息。其語法為:

            public static Logger getLogger( String name)

            通過指定的名字獲得記錄器,如果必要的話,則為這個(gè)名字創(chuàng)建一個(gè)新的記錄器。Name一般取本類的名字,比如:

            static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )

            2.讀取配置文件

            當(dāng)獲得了日志記錄器之后,第二步將配置Log4j環(huán)境,其語法為:

            BasicConfigurator.configure (): 自動(dòng)快速地使用缺省Log4j環(huán)境。
            PropertyConfigurator.configure ( String configFilename) :讀取使用Java的特性文件編寫的配置文件。
            DOMConfigurator.configure ( String filename ) :讀取XML形式的配置文件。

            3.插入記錄信息(格式化日志信息)

            當(dāng)上兩個(gè)必要步驟執(zhí)行完畢,您就可以輕松地使用不同優(yōu)先級(jí)別的日志記錄語句插入到您想記錄日志的任何地方,其語法如下:

            Logger.debug ( Object message ) ;
            Logger.info ( Object message ) ;
            Logger.warn ( Object message ) ;
            Logger.error ( Object message ) ;

          posted @ 2006-08-22 14:28 Lansing 閱讀(367) | 評(píng)論 (0)編輯 收藏
          速度瓶頸問題的提出

            在企業(yè)級(jí)的Java應(yīng)用中,訪問數(shù)據(jù)庫是一個(gè)必備的環(huán)節(jié)。數(shù)據(jù)庫作為數(shù)據(jù)資源的集散地,往往位于企業(yè)級(jí)軟件體系的后方,供前方的應(yīng)用程序訪問。在Java技術(shù)的體系中,應(yīng)用程序是通過JDBC(Java Database Connectivity)接口來訪問數(shù)據(jù)庫的,JDBC支持"建立連接、SQL語句查詢、處理結(jié)果"等基本功能。在應(yīng)用JDBC接口訪問數(shù)據(jù)庫的過程中,只要根據(jù)規(guī)范來操作,這些功能的實(shí)現(xiàn)不會(huì)出差錯(cuò)。但是,有些時(shí)候進(jìn)行數(shù)據(jù)查詢的效率著實(shí)讓開發(fā)人員懊惱不已,明明根據(jù)規(guī)范編寫的程序,卻得不到預(yù)期的運(yùn)行效果,造成了整個(gè)軟件的執(zhí)行效率不高。

            起初,我們把問題歸結(jié)于Java字節(jié)碼加載和執(zhí)行速度的緩慢,緊接著硬件的功能普遍得到了增強(qiáng),證明這樣的想法些許是錯(cuò)誤的,還沒有抓到真正的根本原因。本文將逐步解剖JDBC訪問數(shù)據(jù)庫的機(jī)制,深層分析造成這種速度瓶頸問題的原因,并提出在現(xiàn)有的Java技術(shù)框架下解決這個(gè)速度瓶頸問題的思路和方法。

            JDBC訪問數(shù)據(jù)庫的機(jī)制

          ????????????????
          圖1????????????????????????????????????????????????圖2

            圖1和圖2描述了Java應(yīng)用程序通過JDBC接口訪問數(shù)據(jù)庫的4種驅(qū)動(dòng)模式,也就是底層實(shí)現(xiàn)JDBC接口的模式。對(duì)于這些模式,我們逐一介紹:

            模式4:圖1左邊的分支稱為模式4,它一般是數(shù)據(jù)庫廠商才能實(shí)現(xiàn)的純Java的基于本地協(xié)議的驅(qū)動(dòng),直接調(diào)用DBMS(數(shù)據(jù)庫管理系統(tǒng))使用的網(wǎng)絡(luò)協(xié)議,對(duì)于企業(yè)內(nèi)部互聯(lián)網(wǎng)來說,是一個(gè)實(shí)用的解決方案。

            模式3:圖1右邊的分支稱為模式3,它同樣是一個(gè)純Java驅(qū)動(dòng),不同于模式4的是基于網(wǎng)絡(luò)協(xié)議。它的機(jī)制是將JDBC調(diào)用轉(zhuǎn)換為中間網(wǎng)絡(luò)協(xié)議,然后轉(zhuǎn)換為DBMS協(xié)議。中間網(wǎng)絡(luò)協(xié)議層起到一個(gè)讀取數(shù)據(jù)庫的中間件的作用,能夠連接許多類型的數(shù)據(jù)庫,因而是最靈活的JDBC模式。這種模式的產(chǎn)品比較適用于企業(yè)內(nèi)部互聯(lián)網(wǎng),如若支持國際互聯(lián)網(wǎng),還需添加對(duì)安全、穿過防火墻訪問等的支持。

            模式1:圖2左邊的分支稱為模式1,即通常由Sun公司提供的JDBC-ODBC橋接器。它提供了經(jīng)由一種或多種ODBC驅(qū)動(dòng)進(jìn)行訪問的JDBC接口,而ODBC驅(qū)動(dòng),在很多情況下也即數(shù)據(jù)庫的客戶端,必須加載到客戶機(jī)。因而,它適用于下載和自動(dòng)安裝Java程序不重要、實(shí)驗(yàn)用途或者沒有其它JDBC驅(qū)動(dòng)可用的情況下。

            模式2:圖2右邊的分支成為模式2,類似于JDBC-ODBC橋接器,需要加載到客戶機(jī),卻是一個(gè)部分用Java實(shí)現(xiàn)的驅(qū)動(dòng)接口。它將JDBC調(diào)用轉(zhuǎn)換為對(duì)數(shù)據(jù)庫(Oracle、Sybase、Informix、DB2等)客戶端接口的調(diào)用。

            不同模式的JDBC接口的選擇

            以上闡述的JDBC接口的模式不同,讓我們可以把JDBC接口按照實(shí)現(xiàn)的模式分為四類。有些同仁可能有這樣的體會(huì),選擇不同的JDBC接口會(huì)有不同的訪問速度,為何會(huì)出現(xiàn)這樣的情況?這個(gè)問題的答案是,不同的應(yīng)用需要不同模式的JDBC接口,因而我們在面對(duì)一個(gè)應(yīng)用時(shí),要慎重選擇JDBC接口。

            通常的DBMS都支持微軟提出的ODBC規(guī)范,因而模式1可當(dāng)作您在設(shè)計(jì)和實(shí)現(xiàn)軟件時(shí)的選擇,它易于配置的特性能夠讓你把選擇JDBC等煩惱的問題暫且拋在一邊,讓自己的Java程序能夠及早地正常工作起來。

            一般說來,商業(yè)DBMS的提供者往往會(huì)為自己的數(shù)據(jù)庫提供一個(gè)JDBC接口,應(yīng)用的是模式4。這種模式的優(yōu)勢在于和數(shù)據(jù)庫本身結(jié)合比較緊密,而且是純Java的實(shí)現(xiàn),在企業(yè)級(jí)的軟件應(yīng)用中,應(yīng)該是首選。例如,對(duì)于Oracle數(shù)據(jù)庫來說,有Oracle、SilverStream、DataDirect等公司提供這種類型的驅(qū)動(dòng),其性能往往被評(píng)價(jià)為最高效的、最可靠的驅(qū)動(dòng)程序。但偶爾也有比較麻煩的情況,例如微軟就不會(huì)提供MS SQL的JDBC接口,這時(shí)就需要到Sun的網(wǎng)站(http://industry.java.sun.com/products/jdbc/drivers)查找相關(guān)的模式4驅(qū)動(dòng),上面提到的DataDirect公司(http://www.datadirect-technologies.com/jdbc/jdbc.asp)就提供了支持MS SQL的模式4驅(qū)動(dòng),只是你需要支付750$購買這個(gè)JDBC驅(qū)動(dòng)。

            同樣是純Java實(shí)現(xiàn)的模式3,與模式4相比,優(yōu)勢在于對(duì)多種數(shù)據(jù)庫的支持,體現(xiàn)了其靈活性。在大型的企業(yè)級(jí)的軟件應(yīng)用中,后臺(tái)數(shù)據(jù)庫往往不是一個(gè),而且是由不同的廠商支持的。不過,模式3的JDBC驅(qū)動(dòng)往往提供許多企業(yè)級(jí)的特征,例如SSL安全、支持分布式事務(wù)處理和集中管理等,因而會(huì)對(duì)你特殊的用途有很大的幫助。是否選用,還在于你對(duì)擴(kuò)展應(yīng)用是否有需求以及對(duì)多DBMS的支持。

            談到這兒,我對(duì)模式3和模式4作一個(gè)總結(jié):兩者都是純Java實(shí)現(xiàn)的驅(qū)動(dòng),因而不需要數(shù)據(jù)庫廠商提供附加的軟件,就可以運(yùn)行在任何標(biāo)準(zhǔn)的Java平臺(tái),性能上比較高效、可靠。

            了解上述3種JDBC的實(shí)現(xiàn)模式之后,模式2就更容易闡釋了,你可以理解它為前三者利弊平衡的妥協(xié)產(chǎn)物:

            1. 借鑒模式1利用客戶機(jī)本地代碼庫,加速數(shù)據(jù)訪問的執(zhí)行,但卻摒除ODBC標(biāo)準(zhǔn),而是支持廠商自己指定的性能擴(kuò)展
            2. 借鑒模式3利用多層結(jié)構(gòu),上層用Java實(shí)現(xiàn),利于跨平臺(tái)應(yīng)用和支持多數(shù)據(jù)庫,但下層卻改為本地代碼,加速執(zhí)行速度
            3. 借鑒模式4和數(shù)據(jù)庫結(jié)合緊密的優(yōu)點(diǎn),部分用Java實(shí)現(xiàn),更是對(duì)數(shù)據(jù)庫性能有很大的擴(kuò)展

            這種開放和高性能的特征得到了業(yè)界的肯定,因而被主要的數(shù)據(jù)庫廠商強(qiáng)烈推薦。盡管它需要你下載本地代碼庫到客戶機(jī),但相對(duì)于你訪問數(shù)據(jù)庫速度的提高,這些應(yīng)該只是舉手之勞了。下面對(duì)4種實(shí)現(xiàn)JDBC的模式選擇,歸納一下選擇的順序(當(dāng)然是指你有選擇余地的時(shí)候,不存在的話向后推延):

          編號(hào) 選擇過程分析 選擇順序
          1 實(shí)驗(yàn)性環(huán)境下,盡可能選擇易于配置的驅(qū)動(dòng),利于Java程序的開發(fā),后期可在對(duì)應(yīng)用環(huán)境進(jìn)行判斷后,再對(duì)JDBC模式進(jìn)行選擇 1>2>3>4
          2 小型企業(yè)級(jí)環(huán)境下,不需要對(duì)多數(shù)據(jù)庫的支持,因而模式2和3的有些優(yōu)點(diǎn)并不能體現(xiàn)出來,強(qiáng)烈推薦你選擇模式4的JDBC驅(qū)動(dòng) 4>2=3>1
          3 大型企業(yè)級(jí)環(huán)境下,需要對(duì)多數(shù)據(jù)庫的支持,模式2和3各有千秋,但是更多情況下是你會(huì)選擇速度較快的模式2 2>3>4>1

            對(duì)于不同廠商提供的但應(yīng)用相同模式的JDBC接口,理論上比較不出效率的高低,你只有通過一定的工具,例如Benchmark等,對(duì)它們進(jìn)行比較才能更有利于你的選擇。因?yàn)闀簳r(shí)不存在第三方提供的數(shù)據(jù)比較結(jié)果,所以這些問題需要你對(duì)上述內(nèi)容有了透徹理解之后自行解決。

            Java程序中SQL語句格式的優(yōu)化

            這個(gè)時(shí)候,你也許還在為找不到合適的JDBC驅(qū)動(dòng)而一籌莫展,也許為自己在凌晨3點(diǎn)下載的JDBC驅(qū)動(dòng)通過了測試而欣喜若狂,但是并不說明你對(duì)程序的優(yōu)化工作已經(jīng)無關(guān)緊要了。切記,對(duì)整個(gè)軟件系統(tǒng)的優(yōu)化,包括每個(gè)環(huán)節(jié)的優(yōu)化,要不有可能你會(huì)前功盡棄。我在這兒不和大家討論Java程序的算法,而是簡單闡述一下選擇SQL語句格式的必要和如何選擇對(duì)自己有利的SQL語句格式。看下面兩段程序片斷:

            Code Fragment 1:

            String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE 'Colombian'";
            stmt.executeUpdate(updateString);

            Code Fragment 2:

            PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
            updateSales.setInt(1, 75);
            updateSales.setString(2, "Colombian");
            updateSales.executeUpdate();

            片斷2和片斷1的區(qū)別在于,后者使用了PreparedStatement對(duì)象,而前者是普通的Statement對(duì)象。PreparedStatement對(duì)象不僅包含了SQL語句,而且大多數(shù)情況下這個(gè)語句已經(jīng)被預(yù)編譯過,因而當(dāng)其執(zhí)行時(shí),只需DBMS運(yùn)行SQL語句,而不必先編譯。當(dāng)你需要執(zhí)行Statement對(duì)象多次的時(shí)候,用PreparedStatement對(duì)象將會(huì)大大降低運(yùn)行時(shí)間,當(dāng)然也加快了訪問數(shù)據(jù)庫的速度。

            這種轉(zhuǎn)換也給你帶來很大的便利,不必重復(fù)SQL語句的句法,而只需更改其中變量的值,便可重新執(zhí)行SQL語句。選擇PreparedStatement對(duì)象與否,在于相同句法的SQL語句是否執(zhí)行了多次,而且兩次之間的差別僅僅是變量的不同。如果僅僅執(zhí)行了一次的話,它應(yīng)該和普通的Statement對(duì)象毫無差異,體現(xiàn)不出它預(yù)編譯的優(yōu)越性。

            軟件模型中對(duì)數(shù)據(jù)庫訪問的設(shè)計(jì)模式的優(yōu)化

            在我閱讀J2EE藍(lán)圖和JDO草案的過程中,我發(fā)現(xiàn)了訪問模式對(duì)數(shù)據(jù)庫訪問的影響,因而想在本文中闡述如何針對(duì)自己的軟件需求選擇合適的軟件模式。

            J2EE藍(lán)圖的設(shè)計(jì)者在Java Pet Store示例應(yīng)用中使用了MVC(Model-View-Controller)體系,給許多J2EE設(shè)計(jì)模式提供了背景。我要談及的三種設(shè)計(jì)模式是:Data Access Object、Fast Lane Reader、Page-by-Page Iterator,它們?yōu)榧涌鞌?shù)據(jù)存取速度提供了一些可以在系統(tǒng)設(shè)計(jì)階段值得我們借鑒的想法。

            Data Access Object

            將商業(yè)邏輯從數(shù)據(jù)存取邏輯中分離出來,把存取的資源改編,從而使資源可以容易和獨(dú)立地轉(zhuǎn)變。

            依賴于底層數(shù)據(jù)資源的特殊要素(例如數(shù)據(jù)庫的供應(yīng)商)的商業(yè)組件,常將商業(yè)邏輯和數(shù)據(jù)存取邏輯配合起來,只能使用特殊類型的資源,而使用不同類型的資源時(shí),復(fù)用將會(huì)非常困難,因此,只能服務(wù)于有限的市場領(lǐng)域。DAO(Data Access Object)即是將數(shù)據(jù)存取邏輯從EJB中抽去出來抽象為一個(gè)獨(dú)立的接口,EJB根據(jù)接口的操作執(zhí)行商業(yè)邏輯,而接口針對(duì)使用的數(shù)據(jù)資源實(shí)現(xiàn)為DAO對(duì)象。

            在Java Pet Shop這個(gè)例子中,OrderEJB組件通過關(guān)聯(lián)的OrderDAO類訪問數(shù)據(jù)庫,自身則關(guān)注于商業(yè)邏輯的實(shí)現(xiàn)。在調(diào)度階段,將配置某一類(OrderDAOCS、OrderDAOOracle或OrderDAOSybase)為OrderDAO的實(shí)現(xiàn),而OrderEJB無須任何更改。圖3更能幫助你明白其中的道理:


          圖3 Data Access Object的設(shè)計(jì)模式

            此舉增加了數(shù)據(jù)存取的彈性、資源的獨(dú)立性和擴(kuò)展性,但復(fù)雜度有相應(yīng)的提高,其它附帶的問題我們不在這兒討論。

            Fast Lane Reader

            拋棄EJB,加速只讀數(shù)據(jù)的存取。

            有些時(shí)候,高效地存取數(shù)據(jù)比獲得最新的數(shù)據(jù)更重要。在Java Pet Store中,當(dāng)一個(gè)用戶瀏覽商店的目錄時(shí),屏幕與數(shù)據(jù)庫內(nèi)容吻合不是至關(guān)緊要的,相反,迅速顯示和重新獲得非常重要。FLR模式可以加速從資源中重新獲得大型的列數(shù)據(jù)項(xiàng)的速度,它不用EJB,而是更直接地通過DAO來存取數(shù)據(jù),從而消除EJB的經(jīng)常開支(例如遠(yuǎn)程方法調(diào)用、事務(wù)管理和數(shù)據(jù)序列化等)。

            在Java Pet Store這個(gè)例子中,當(dāng)一個(gè)用戶瀏覽目錄時(shí),通過CatalogDAO(而不是CatalogEJB)從數(shù)據(jù)庫加載數(shù)據(jù)項(xiàng),而CatalogDAO是一個(gè)Fast Lane Reader的實(shí)例,使得讀訪問變得迅速,如圖4:


          圖4 Fast Lane Reader設(shè)計(jì)模式

            與DAO模式不同的是,F(xiàn)LR是一個(gè)優(yōu)化的模式,但不是要替代原有的訪問機(jī)制,而是作為補(bǔ)充使其完備。當(dāng)你頻繁地只讀大型的列數(shù)據(jù)和不必存取最新的數(shù)據(jù)時(shí),使用FLR將是非常合適的。

            Page-by-Page Iterator

            為了高效地存取大型的遠(yuǎn)程數(shù)據(jù)列,一下子通過重新獲得其元素為一個(gè)子列的Value Object(提高遠(yuǎn)程傳輸效率的設(shè)計(jì)模式,這兒不詳盡描述)。

            分布式數(shù)據(jù)庫的應(yīng)用經(jīng)常需要用戶考慮一長列數(shù)據(jù)項(xiàng),例如一個(gè)目錄或一個(gè)搜索結(jié)果的集合。在這些情況下,立刻提供全列的數(shù)據(jù)經(jīng)常不必要(用戶并不是對(duì)所有的數(shù)據(jù)項(xiàng)感興趣)或不可能(沒有足夠的空間)。此外,當(dāng)重新獲得一列數(shù)據(jù)項(xiàng)時(shí),使用Entity Bean的代價(jià)將非常高昂,一個(gè)開銷來自于使用遠(yuǎn)程探測器來收集Requested Bean,另外,更大的開銷來自對(duì)每個(gè)Bean產(chǎn)生遠(yuǎn)程調(diào)用以從用戶獲得數(shù)據(jù)。

            通過Iterator,客戶機(jī)對(duì)象能一下子重新獲得一個(gè)子列或者頁的Value Object,每一頁都剛好滿足客戶機(jī)的需求,因此,程序使用較少的資源滿足了客戶機(jī)的立刻需求。

            在Java Pet Store這個(gè)例子中,JSP頁面product.jsp任何時(shí)候只顯示一個(gè)數(shù)據(jù)列的一部分,從ProductItemListTag(Page-by-Page Iterator)重新獲得數(shù)據(jù)項(xiàng),當(dāng)客戶機(jī)希望看到列中的別的數(shù)據(jù)項(xiàng),product.jsp再次調(diào)用Iterator重新獲得這些數(shù)據(jù)項(xiàng),流程見圖5:


          圖5 Page-by-Page Iterator設(shè)計(jì)模式

            以上設(shè)計(jì)模式的應(yīng)用向我們表明,在某些特殊情況下,優(yōu)化對(duì)數(shù)據(jù)庫的訪問模型,既可滿足用戶的需求又可提高訪問數(shù)據(jù)庫的效率。這給我們一個(gè)思路,就是:在你的硬件環(huán)境可能會(huì)產(chǎn)生瓶頸的情況下,可以通過對(duì)軟件模型的優(yōu)化來達(dá)到滿足需求的目的。上述三種設(shè)計(jì)模式的應(yīng)用情形為:

          Data Access Object 需要將商業(yè)邏輯和數(shù)據(jù)存取邏輯分離;
          在調(diào)度的時(shí)刻,需要支持選擇數(shù)據(jù)源的類型;
          使用的數(shù)據(jù)源的類型的變化,對(duì)商業(yè)對(duì)象或其它客戶端完成數(shù)據(jù)存取沒有影響。
          Fast Lane Reader 面對(duì)大型的列數(shù)據(jù),需要經(jīng)常的只讀訪問;
          訪問最新的數(shù)據(jù)并不是至關(guān)緊要的事情。
          Page-by-Page Iterator 存取大型的服務(wù)器端數(shù)據(jù)列;
          任何時(shí)刻,用戶只對(duì)列的一部分內(nèi)容感興趣;
          整個(gè)列的數(shù)據(jù)不適合在客戶端顯示;
          整個(gè)列的數(shù)據(jù)不適合在存儲(chǔ)器中保存;
          傳輸整個(gè)列的數(shù)據(jù)將耗費(fèi)太多的時(shí)間。

            在顯示商品目錄的時(shí)候,我們選擇了DAO和FLR的結(jié)合,因?yàn)樗鼈儍烧叩臈l件都得到了滿足(需要分離商業(yè)邏輯和數(shù)據(jù)存取邏輯,經(jīng)常的只讀訪問和對(duì)即時(shí)性不敏感),此時(shí)應(yīng)用將會(huì)大大發(fā)揮它們的優(yōu)點(diǎn)。而在進(jìn)行內(nèi)容檢索的時(shí)候,我們會(huì)選擇PPI,因?yàn)橐苍S檢索出了上千條的記錄,但是用戶沒有興趣立即閱讀全部內(nèi)容,而是一次十條地閱讀,或者他在閱讀完前十條記錄后發(fā)覺自己的目的已經(jīng)達(dá)到,接下來瀏覽別的網(wǎng)頁了,都不必我們一次性地傳輸上千條記錄給他,所以也是PPI的應(yīng)用條件得到了滿足,結(jié)果則是此模式的優(yōu)點(diǎn)得到了發(fā)揮,又不影響全局的數(shù)據(jù)訪問。

            在進(jìn)行軟件模型的設(shè)計(jì)時(shí),整體的框架可以應(yīng)用某些優(yōu)秀的、通用的設(shè)計(jì)模式,這樣既加快模型的建立速度,又能和其它系統(tǒng)集成。但是,碰到一些瓶頸問題的情況下,我們就需要對(duì)局部的設(shè)計(jì)模式做一些調(diào)整,以優(yōu)化整個(gè)系統(tǒng),上述三個(gè)模式就是對(duì)原有體系的補(bǔ)充,它們并沒有對(duì)整體的框架做出巨大的改變,卻突破了某些瓶頸(瓶頸往往是局部的)障礙,讓我們的產(chǎn)品更好地服務(wù)于用戶。

            將深入研究的問題

            開篇至今,我們主要探討了軟件層次上的解決問題,但是,必須肯定一點(diǎn),如果你的硬件環(huán)境非常差(運(yùn)行Java都有困難)或非常好(額外的存儲(chǔ)空間、超快的運(yùn)算速度和富裕的網(wǎng)絡(luò)帶寬),上述途徑對(duì)你來說很難有大的幫助。前一種情況,我建議你升級(jí)硬件設(shè)備到軟件廠商推薦的配置(強(qiáng)烈反對(duì)最小配置),以使應(yīng)用服務(wù)器、數(shù)據(jù)庫、Java等軟件能夠運(yùn)行自如;后一種情況,我沒什么話可說,花錢是解決這個(gè)問題最好的辦法。

            本文并未談及線程池和告訴緩沖這兩個(gè)非常重要的概念,因?yàn)楣P者認(rèn)為,它們是針對(duì)局部時(shí)間高訪問量的瓶頸問題的解決,不能理解為簡單的速度瓶頸問題,所以我會(huì)在下一篇文章中分析這種特殊的情況和提出解決問題的辦法。也許你對(duì)這一點(diǎn)更關(guān)心一些,認(rèn)為自己的問題就出在這個(gè)地方,這是非常好的思考問題的方式,你已經(jīng)抓住了問題的關(guān)鍵。但是,我還是建議你通讀一下本文,讓自己對(duì)速度瓶頸問題有更好的理解,并掌握在解決問題的過程中,分辨常態(tài)和暫態(tài),從而選擇不同的思路入手。其實(shí),本文談及的就是速度瓶頸問題的常態(tài),而下一篇文章討論的將會(huì)是暫態(tài),希望你能夠漸入佳境。

            JDO(Java Data Object)是需要我們關(guān)注的一個(gè)API,它定義了新的數(shù)據(jù)存取模型,直接借鑒了DAO設(shè)計(jì)模式。不同的數(shù)據(jù)源,有不同的數(shù)據(jù)存取技術(shù),就有不同的API供開發(fā)人員使用。JDO正是為了解決這個(gè)問題而產(chǎn)生的,它實(shí)現(xiàn)了即插即用的數(shù)據(jù)存取的實(shí)現(xiàn)和持久信息(包括企業(yè)數(shù)據(jù)和本地存儲(chǔ)的數(shù)據(jù))以Java為中心的視圖。因此,開發(fā)人員只關(guān)注創(chuàng)建那些實(shí)現(xiàn)商業(yè)邏輯的類和用它們來表現(xiàn)數(shù)據(jù)源的數(shù)據(jù),而這些類和數(shù)據(jù)源之間的映射則由那些EIS領(lǐng)域的專家來完成。如果大家對(duì)JDO感興趣的話,那么我會(huì)寫第三篇文章把其詳細(xì)介紹給大家,并給出示例應(yīng)用。

          posted @ 2006-08-22 09:32 Lansing 閱讀(445) | 評(píng)論 (0)編輯 收藏
          批量處理JDBC語句提高處理速度

          作者:佚名????來自:未知

            有時(shí)候JDBC運(yùn)行得不夠快,這使得有些程序員使用數(shù)據(jù)庫相關(guān)的存儲(chǔ)過程。作為一個(gè)替代方案,可以試試使用Statement 的批量處理特性看看能否同時(shí)執(zhí)行所有的SQL以提高速度。

            存儲(chǔ)過程的最簡單的形式就是包含一系列SQL語句的過程,將這些語句放在一起便于在同一個(gè)地方管理也可以提高速度。Statement 類可以包含一系列SQL語句,因此允許在同一個(gè)數(shù)據(jù)庫事務(wù)執(zhí)行所有的那些語句而不是執(zhí)行對(duì)數(shù)據(jù)庫的一系列調(diào)用。

            使用批量處理功能涉及下面的兩個(gè)方法:
            · addBatch(String) 方法
            · executeBatch方法

            如果你正在使用Statement 那么addBatch 方法可以接受一個(gè)通常的SQL語句,或者如果你在使用PreparedStatement ,那么也可以什么都不向它增加。executeBatch 方法執(zhí)行那些SQL語句并返回一個(gè)int值的數(shù)組,這個(gè)數(shù)組包含每個(gè)語句影響的數(shù)據(jù)的行數(shù)。如果將一個(gè)SELECT語句或者其他返回一個(gè)ResultSet的SQL語句放入批量處理中就會(huì)導(dǎo)致一個(gè)SQLException異常。

            關(guān)于java.sql.Statement 的簡單范例可以是:

            Statement stmt = conn.createStatement();
            stmt.insert("DELETE FROM Users");
            stmt.insert("INSERT INTO Users VALUES("rod", 37, "circle")");
            stmt.insert("INSERT INTO Users VALUES("jane", 33, "triangle")");
            stmt.insert("INSERT INTO Users VALUES("freddy", 29, "square")");
            int[] counts = stmt.executeBatch();

            PreparedStatement 有些不同,它只能處理一部分SQL語法,但是可以有很多參數(shù),因此重寫上面的范例的一部分就可以得到下面的結(jié)果:

            // 注意這里沒有DELETE語句
            PreparedStatement stmt = conn.prepareStatement("INSERT INTO Users VALUES(?,?,?)");

            User[ ] users = ...;
            for(int i=0; i<users.length; i++) {
             stmt.setInt(1, users[i].getName());
             stmt.setInt(2, users[i].getAge());
             stmt.setInt(3, users[i].getShape());
             stmt.addBatch( );
            }
            int[ ] counts = stmt.executeBatch();

            如果你不知道你的語句要運(yùn)行多少次,那么這是一個(gè)很好的處理SQL代碼的方法。在不使用批量處理的情況下,如果添加50個(gè)用戶,那么性能就有影響,如果某個(gè)人寫了一個(gè)腳本添加一萬個(gè)用戶,程序可能變得很糟糕。添加批處理功能就可以幫助提高性能,而且在后面的那種情況下代碼的可讀性也更好。

          posted @ 2006-08-22 09:24 Lansing 閱讀(433) | 評(píng)論 (0)編輯 收藏
               摘要: Avalon的簡要?dú)v史以及創(chuàng)建它所有的設(shè)計(jì)原則概述 事情是從Apache JServ項(xiàng)目開始的。Stefano Mazzocchi和其它協(xié)助開發(fā)Apache JServ的人員認(rèn)識(shí)到項(xiàng)目中所用到的一些模式很通用,足以用于創(chuàng)建一個(gè)服務(wù)器框架。 在1999年1月27日,星期三(在JServ ...  閱讀全文
          posted @ 2006-08-18 20:14 Lansing 閱讀(2398) | 評(píng)論 (0)編輯 收藏
          The Grammar of the Java Programming Language
          Identifier:
          ??????? IDENTIFIER

          QualifiedIdentifier:
          ??????? Identifier { . Identifier }

          Literal:
          ??????? IntegerLiteral
          ??????? FloatingPointLiteral
          ??????? CharacterLiteral
          ??????? StringLiteral
          ??????? BooleanLiteral
          ??????? NullLiteral

          Expression:
          ??????? Expression1 [AssignmentOperator Expression1]]

          AssignmentOperator:

          ??????? =
          ??????? +=
          ??????? -=
          ??????? *=
          ??????? /=
          ??????? &=
          ??????? |=
          ??????? ^=
          ??????? %=
          ??????? <<=
          ??????? >>=
          ??????? >>>=

          Type:
          ??????? Identifier [TypeArguments]{?? .?? Identifier [TypeArguments]} {
          []}
          ??????? BasicType

          TypeArguments:
          ??????? < TypeArgument {, TypeArgument} >

          TypeArgument:
          ??????? Type
          ???????
          ? [( extends |super ) Type]

          StatementExpression:
          ??????? Expression

          ConstantExpression:
          ??????? Expression

          Expression1:
          ??????? Expression2 [Expression1Rest]

          Expression1Rest:
          ??????? ? ? Expression? :?? Expression1

          Expression2 :
          ??????? Expression3 [Expression2Rest]

          Expression2Rest:
          ??????? {InfixOp Expression3}
          ??????? Expression3 instanceof Type

          InfixOp:

          ??????? ||
          ??????? &&
          ??????? |
          ??????? ^
          ??????? &
          ??????? ==
          ??????? !=
          ??????? <
          ??????? >
          ??????? <=
          ??????? >=
          ??????? <<
          ??????? >>
          ??????? >>>
          ??????? +
          ??????? -
          ??????? *
          ??????? /
          ??????? %

          Expression3:
          ??????? PrefixOp Expression3
          ???????
          (?? Expression | Type? ) ? Expression3
          ??????? Primary {Selector} {PostfixOp}

          Primary:
          ??????? ParExpression
          ??????? NonWildcardTypeArguments (ExplicitGenericInvocationSuffix
          | this
          Arguments)

          ? this[Arguments]
          ? superSuperSuffix
          ??????? Literal

          ? newCreator
          ??????? Identifier { . Identifier }[ IdentifierSuffix]
          ??????? BasicType {
          []} .class
          ?? void.class

          IdentifierSuffix:
          ??????? [ ( ] {[]} .?? class | Expression ])
          ??????? Arguments
          ??????? .?? (
          class | ExplicitGenericInvocation | this | superArguments | new
          [NonWildcardTypeArguments] InnerCreator )

          ExplicitGenericInvocation:
          ??????? NonWildcardTypeArguments ExplicitGenericInvocationSuffix

          NonWildcardTypeArguments:
          ??????? < TypeList >


          ExplicitGenericInvocationSuffix:
          ???? super SuperSuffix
          ??????? Identifier Arguments


          PrefixOp:

          ??????? ++
          ??????? --
          ??????? !
          ??????? ~
          ??????? +
          ??????? -

          PostfixOp:

          ??????? ++
          ??????? --

          Selector: Selector:
          ??????? . Identifier [Arguments]
          ??????? . ExplicitGenericInvocation
          ??????? .
          this
          ?? .super SuperSuffix
          ??????? . new [NonWildcardTypeArguments] InnerCreator
          ??????? [ Expression ]

          SuperSuffix:
          ??????? Arguments
          ??????? . Identifier [Arguments]

          BasicType:

          ? byte
          ? short
          ? char
          ? int
          ? long
          ? float
          ? double
          ? boolean

          Arguments:
          ??????? ( [Expression { , Expression }] )

          Creator:
          ??????? [NonWildcardTypeArguments] CreatedName ( ArrayCreatorRest? |
          ClassCreatorRest )

          CreatedName:
          ??????? Identifier [NonWildcardTypeArguments] {. Identifier
          [NonWildcardTypeArguments]}

          InnerCreator:
          ??????? Identifier ClassCreatorRest

          ArrayCreatorRest:
          ???????
          [ ( ] {[]} ArrayInitializer | Expression ] {[ Expression ]} {[]} )

          ClassCreatorRest:
          ???????? Arguments [ClassBody]

          ArrayInitializer:
          ??????? { [VariableInitializer {, VariableInitializer} [,]] }

          VariableInitializer:
          ??????? ArrayInitializer
          ??????? Expression

          ParExpression:
          ??????? ( Expression )

          Block:
          ??????? { BlockStatements }

          BlockStatements:
          ??????? { BlockStatement }

          BlockStatement :
          ??????? LocalVariableDeclarationStatement
          ??????? ClassOrInterfaceDeclaration
          ??????? [Identifier :] Statement

          LocalVariableDeclarationStatement:
          ??????? [
          final] Type VariableDeclarators?? ;

          Statement:
          ??????? Block
          ???????
          assert Expression [ : Expression] ;
          ???? if ParExpression Statement [else Statement]
          ???? for ( ForControl ) Statement
          ???? while ParExpression Statement
          ???? do Statement while ParExpression?? ;
          ???? try Block ( Catches | [Catches] finally Block )
          ???? switch ParExpression { SwitchBlockStatementGroups }
          ???? synchronized ParExpression Block
          ???? return [Expression] ;
          ???? throw Expression? ;
          ???? break [Identifier]
          ???? continue [Identifier]
          ???????
          ;
          ??????? StatementExpression
          ;
          ??????? Identifier??
          : ? Statement

          Catches:
          ??????? CatchClause {CatchClause}

          CatchClause:
          ???? catch ( FormalParameter ) Block

          SwitchBlockStatementGroups:
          ??????? { SwitchBlockStatementGroup }

          SwitchBlockStatementGroup:
          ??????? SwitchLabel BlockStatements

          SwitchLabel:
          ???? case ConstantExpression?? :
          ???????
          case EnumConstantName :
          ??????? default?? :

          MoreStatementExpressions:
          ??????? { , StatementExpression }

          ForControl:
          ??????? ForVarControl
          ??????? ForInit;?? [Expression]?? ; [ForUpdate]

          ForVarControl
          ??????? [
          final] [Annotations] Type Identifier ForVarControlRest

          Annotations:
          ??????? Annotation [Annotations]

          Annotation:
          ???????
          @ TypeName [( [Identifier =] ElementValue)]

          ElementValue:
          ??????? ConditionalExpression
          ??????? Annotation
          ??????? ElementValueArrayInitializer

          ConditionalExpression:
          ??????? Expression2 Expression1Rest

          ??? ElementValueArrayInitializer:
          ???????
          { [ElementValues] [,] }

          ??? ElementValues:
          ??????? ElementValue [ElementValues]

          ForVarControlRest:
          ??????? VariableDeclaratorsRest;?? [Expression]?? ;?? [ForUpdate]
          ??????? : Expression

          ForInit:
          ??????? StatementExpression Expressions

          Modifier:
          ? Annotation

          ? public
          ? protected
          ? private
          ? static
          ? abstract
          ? final
          ? native
          ? synchronized
          ? transient
          ? volatile
          ??????? strictfp

          VariableDeclarators:
          ??????? VariableDeclarator { ,?? VariableDeclarator }

          VariableDeclaratorsRest:
          ??????? VariableDeclaratorRest { ,?? VariableDeclarator }

          ConstantDeclaratorsRest:
          ??????? ConstantDeclaratorRest { ,?? ConstantDeclarator }

          VariableDeclarator:
          ??????? Identifier VariableDeclaratorRest

          ConstantDeclarator:
          ??????? Identifier ConstantDeclaratorRest

          VariableDeclaratorRest:
          ??????? {
          []} [? =?? VariableInitializer]

          ConstantDeclaratorRest:
          ??????? {
          []} =?? VariableInitializer

          VariableDeclaratorId:
          ??????? Identifier {
          []}

          CompilationUnit:
          ??????? [[Annotations]
          package QualifiedIdentifier?? ;? ] {ImportDeclaration}
          {TypeDeclaration}

          ImportDeclaration:
          ???? import [ static] Identifier {?? .?? Identifier } [?? .???? *?? ] ;

          TypeDeclaration:
          ??????? ClassOrInterfaceDeclaration
          ??????? ;

          ClassOrInterfaceDeclaration:
          ??????? {Modifier} (ClassDeclaration
          | InterfaceDeclaration)

          ClassDeclaration:
          ??????? NormalClassDeclaration
          ??????? EnumDeclaration

          NormalClassDeclaration:
          ???? class Identifier [TypeParameters] [extends Type] [implements TypeList]
          ClassBody

          TypeParameters:
          ??????? < TypeParameter {, TypeParameter} >

          TypeParameter:
          ??????? Identifier [
          extends Bound]

          Bound:
          ???????? Type {& Type}


          EnumDeclaration:
          ???????
          enum Identifier [implements TypeList] EnumBody

          EnumBody:
          ??????? { [EnumConstants] [,] [EnumBodyDeclarations] }

          EnumConstants:
          ??????? EnumConstant
          ??????? EnumConstants , EnumConstant

          EnumConstant:
          ??????? Annotations Identifier [Arguments] [ClassBody]

          EnumBodyDeclarations:
          ??????? ; {ClassBodyDeclaration}

          InterfaceDeclaration:
          ??????? NormalInterfaceDeclaration
          ??????? AnnotationTypeDeclaration

          NormalInterfaceDeclaration:
          ???? interface Identifier [ TypeParameters] [extends TypeList] InterfaceBody

          TypeList:
          ??????? Type {? ,?? Type}

          AnnotationTypeDeclaration:
          ???????
          @ interface Identifier AnnotationTypeBody

          ??? AnnotationTypeBody:
          ??????? { [AnnotationTypeElementDeclarations] }

          ??? AnnotationTypeElementDeclarations:
          ??????? AnnotationTypeElementDeclaration
          ??????? AnnotationTypeElementDeclarations AnnotationTypeElementDeclaration

          AnnotationTypeElementDeclaration:
          ??????? {Modifier} AnnotationTypeElementRest

          AnnotationTypeElementRest:
          ???????? Type Identifier AnnotationMethodOrConstantRest;
          ??????? ClassDeclaration
          ??????? InterfaceDeclaration
          ??????? EnumDeclaration
          ??????? AnnotationTypeDeclaration

          ??????? AnnotationMethodOrConstantRest:
          ??????? AnnotationMethodRest
          ??????? AnnotationConstantRest

          AnnotationMethodRest:
          ??????? ( ) [DefaultValue]

          AnnotationConstantRest:
          ??????? VariableDeclarators


          ??? DefaultValue:
          ???????
          default ElementValue

          ClassBody:
          ???????
          { {ClassBodyDeclaration} }

          InterfaceBody:
          ???????
          { {InterfaceBodyDeclaration} }

          ClassBodyDeclaration:
          ???????
          ;
          ??????? [
          static] Block
          ??????? {Modifier} MemberDecl

          MemberDecl:
          ??????? GenericMethodOrConstructorDecl
          ??????? MethodOrFieldDecl
          ???????
          void Identifier VoidMethodDeclaratorRest
          ??????? Identifier ConstructorDeclaratorRest
          ??????? InterfaceDeclaration
          ??????? ClassDeclaration

          GenericMethodOrConstructorDecl:
          ??????? TypeParameters GenericMethodOrConstructorRest

          GenericMethodOrConstructorRest:
          ??????? (Type
          | void) Identifier MethodDeclaratorRest
          ??????? Identifier ConstructorDeclaratorRest

          MethodOrFieldDecl:
          ??????? Type Identifier MethodOrFieldRest

          MethodOrFieldRest:
          ??????? VariableDeclaratorRest
          ??????? MethodDeclaratorRest

          InterfaceBodyDeclaration:
          ???????
          ;
          ??????? {Modifier} InterfaceMemberDecl

          InterfaceMemberDecl:
          ??????? InterfaceMethodOrFieldDecl
          ??????? InterfaceGenericMethodDecl
          ???????
          void Identifier VoidInterfaceMethodDeclaratorRest
          ??????? InterfaceDeclaration
          ??????? ClassDeclaration

          InterfaceMethodOrFieldDecl:
          ??????? Type Identifier InterfaceMethodOrFieldRest

          InterfaceMethodOrFieldRest:
          ??????? ConstantDeclaratorsRest ;
          ??????? InterfaceMethodDeclaratorRest

          MethodDeclaratorRest:
          ??????? FormalParameters {
          []} [throwsQualifiedIdentifierList] ( MethodBody |?? ;
          )

          VoidMethodDeclaratorRest:
          ??????? FormalParameters [
          throws QualifiedIdentifierList] ( MethodBody |?? ;? )

          InterfaceMethodDeclaratorRest:
          ??????? FormalParameters {
          []} [throwsQualifiedIdentifierList]? ;

          InterfaceGenericMethodDecl:
          ??????? TypeParameters (Type
          | void) Identifier InterfaceMethodDeclaratorRest

          VoidInterfaceMethodDeclaratorRest:
          ??????? FormalParameters [
          throws QualifiedIdentifierList]?? ;

          ConstructorDeclaratorRest:
          ??????? FormalParameters [
          throws QualifiedIdentifierList] MethodBody

          QualifiedIdentifierList:
          ??????? QualifiedIdentifier {? ,?? QualifiedIdentifier}

          FormalParameters:
          ??????? ( [FormalParameterDecls] )

          FormalParameterDecls:
          ??????? [
          final] [Annotations] Type FormalParameterDeclsRest]

          FormalParameterDeclsRest:
          ??????? VariableDeclaratorId [ , FormalParameterDecls]
          ??????? ... VariableDeclaratorId

          MethodBody:
          ??????? Block

          EnumConstantName:
          ??????? Identifier
          posted @ 2006-08-18 09:00 Lansing 閱讀(375) | 評(píng)論 (0)編輯 收藏
          <2006年8月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          歡迎探討,努力學(xué)習(xí)Java哈

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          Lansing's Download

          Lansing's Link

          我的博客

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 潮安县| 赤壁市| 庆阳市| 玉龙| 渭源县| 呈贡县| 许昌市| 松原市| 喀喇沁旗| 邮箱| 宁国市| 华坪县| 辽宁省| 横山县| 玉屏| 尖扎县| 宁武县| 镶黄旗| 正阳县| 柳州市| 韶关市| 遵义县| 江门市| 定安县| 庐江县| 敦化市| 中卫市| 保靖县| 桃江县| 铜陵市| 海晏县| 云浮市| 尚志市| 万源市| 遂昌县| 阜平县| 栖霞市| 黔江区| 财经| 平潭县| 麻江县|