程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 在Apache目錄服務器中存儲Java對象,第1部分 - 深入Apache目錄服務器

在Apache目錄服務器中存儲Java對象,第1部分 - 深入Apache目錄服務器

編輯:關於JAVA

簡介:這個兩部分的系列介紹了在 Apache 目錄服務器(ApacheDS)中保存 Java™ 對象的步驟 。在第 1 部分中,作者 Bilal Siddiqui 介紹了 ApacheDS,並提供了 ApacheDS 核心架構的概述。因為 主要把 ApacheDS 用作保存 Java 對象的 LDAP 服務器,所以 Bilal 提供了對 LDAP 概念和術語的快速 概述。他還介紹了如何用 JXplorer 查看 LDAP 模式組件,例如屬性類型和對象類,還介紹了如何在 ApacheDS 中輸入數據對象。文章末尾概述了 Java 對象的序列化和遠程方法調用,並用它們把 Java 對 象保存在 ApacheDS 中,為 第 2 部分中 實踐性更強的方法做好准備。

Apache 目錄服務器是眾多的 Internet 協議中的一個開放源碼的、基於 Java 的實現。ApacheDS 的 核心是目錄服務,可以保存數據,並對不同類型的數據進行搜索操作。協議的實現在目錄服務器頂層工作 ,提供與數據存儲、搜索和檢索有關的 Internet 服務。

ApacheDS 最重要的特性可能是利用不同 協議公開目錄服務的能力。這意味著可以把應用程序的數據(包括運行時的 Java 對象)保存在 ApacheDS 中,而不同的客戶機可以使用不同的協議來利用數據。由 ApacheDS 實現的最重要的協議是輕 量級目錄訪問協議(LDAP)。ApacheDS 充當 LDAP 服務器,偵聽請求,與內部核心目錄服務協調,響應 LDAP 請求。

在這個兩部分的系列中,我將介紹核心的 ApacheDS 架構,並介紹在 ApacheDS 中保 存運行時 Java 對象的全部步驟。因為我對 ApacheDS 的關注幾乎全在它作為 LDAP 服務器實現上,所以 本系列的第 1 部分主要介紹 LDAP 功能和術語。但在進入這部分之前,我要介紹 ApacheDS 模塊化的可 擴展架構,並解釋如何用它把新的協議實現和 Internet 服務插入 ApacheDS。對 ApacheDS 核心目錄服 務工作方式的理解,有助於後面理解它提供 LDAP 功能的方式。

要跟上這篇文章的討論,需要 下 載並安裝 ApacheDS 和 JXplorer。可能還要下載 完整源代碼 供文章使用。

ApacheDS 中的目錄 服務

目錄服務 是保存和組織數據的應用程序。目錄服務處理不需要頻繁更新的數據,例如系統用 戶的個人數據(例如姓名、地址、電話號碼)或者車間的生產能力(例如安裝的設備的數量、型號和生產 能力)。在本系列的第 2 部分中,將介紹一個整合了這兩種類型數據的示例應用程序。現在,我把重點 放在 ApacheDS 提供目錄服務的方式上。

ApacheDS 實現 JNDI

在圖 1 中可以看到, ApacheDS 為自己的核心目錄服務實現了 Java 名稱和目錄接口(JNDI)包裝器。JNDI 是 Java 接口,定 義了執行目錄操作的方法,例如在目錄中保存數據和搜索保存的數據。JNDI 是 Java 2 企業版(J2EE) 和 Java 2 標准版(J2SE)的組成部分。其中 J2SE 只包含客戶端 JNDI 支持,而 J2EE 容器通常包含服 務器端 JNDI 實現。J2EE 容器可以通過 ApacheDS 的 JNDI 包裝器利用它的目錄服務,如圖 1 所示:

圖 1. ApacheDS 在 J2EE 容器內工作

JNDI 中的接口集提供了 目錄服務的抽象。JNDI 實現提供了與目錄服務對話的實際邏輯(例如,Java 平台自帶了針對 LDAP 的 JNDI 實現)。只要擁有針對這一類型的 JNDI 實現,您就可以用 JNDI 與任何類型的目錄服務對話。如 果想在基於 Java 的客戶機應用程序中使用 JNDI,就需要 JNDI 的客戶端實現。客戶端 JNDI 實現提供 的類,實現的是進行目錄操作請求的 JNDI。

ApacheDS 實現服務器端 JNDI。這意味著它包含的類 ,實現的是對目錄操作請求進行響應的 JNDI 接口。正如前面指出的(如 圖 1 所示),J2EE 容器可以 通過 ApacheDS 的 JNDI 包裝器利用它的目錄服務。

可插入的協議支持

圖 1 只顯示了 ApacheDS 的一個使用模型。ApacheDS 的用途不僅僅是嵌在 J2EE 容器內作為目錄服務。可以用 ApacheDS 實現任何需要後端目錄服務的協議。甚至可以用它同時為各種類型的協議服務;例如,當前的 ApacheDS 實現就同時實現了 LDAP 和 Kerberos。而且,ApacheDS 中支持的協議的列表仍在增長。

ApacheDS 擁有靈活的可擴展的架構,因此可以實現新的協議。在圖 2 中可以看到 ApacheDS 架 構的模型,它工作在 圖 1 所示的 JNDI 包裝器之上:

圖 2. ApacheDS 靈活的可擴展的架構

可以看到,ApacheDS 使用一套叫做多用途網絡應用程序接口(MINA)的接口。MINA 支持把新的協議實現插入 ApacheDS。在介 紹這些內容之前,我要解釋一下 MINA 的工作方式。

MINA 如何工作

MINA 中的接口包含的 方法可以生成特定協議的工廠對象。這些工廠對象提供了把新協議實現插入 ApacheDS 的手段。協議實現 負責實現 MINA 接口,ApacheDS 框架依靠 MINA 包含的方法與協議實現對話。

例如,MINA 有一 個叫做 ProtocolProvider 的接口,該接口有一個 getCodecFactory() 方法。 ProtocolProvider.getCodecFactory() 方法返回一個對象,公開另一個叫做 ProtocolCodecFactory 的 MINA 接口。

ApacheDS 中的協議實現,實現了 ProtocolProvider 接口。例如,ApacheDS 中的 LDAP 實現擁有一個叫做 LDAPProtocolProvider 的類,這個類實現了 ProtocolProvider 接口。

LDAPProtocolProvider 中的 getCodecFactory() 方法返回一個公開 ProtocolCodecFactory 接 口的對象。這個 ProtocolCodecFactory 是一個工廠對象,ApacheDS 框架用它創建特定於 LDAP 的編碼 和解碼對象。

ProtocolCodecFactory 包含 newEncoder() 和 newDecoder() 方法,這兩個方法返 回的對象公開 MINA 的 ProtocolEncoder 和 ProtocolDecoder 接口。特定於協議的編碼對象公開 ProtocolEncoder 接口,而解碼對象則公開 ProtocolDecoder 接口。

MINA 的編碼和解碼框架

猜也猜得出來,ApacheDS 框架使用特定於協議的 ProtocolDecoder 實例對協議請求進行解碼, 這樣就可以在處理請求之前理解請求的意義。在解碼之後,ApacheDS 處理請求。例如,如果請求是一個 LDAP 搜索請求,那麼 ApacheDS 就會在後端目錄服務中搜索需要的數據,並提取搜索結果。

在找 到需要的搜索結果後,ApacheDS 框架用特定於協議的 ProtocolEncoder 對象編碼搜索結果。在 LDAP 搜 索請求的示例中,ApacheDS 會使用特定於 LDAP 的 ProtocolEncoder 對象在向請求客戶機發送響應之前 對搜索結構進行編碼。

MINA 的服務框架

MINA 還有處理服務的類。任何服務提供者都可以 把自己注冊到一個服務注冊表,而協議提供者會與提供服務的提供者類一起注冊。然後協議提供者就把協 議請求映射成 JNDI 操作。簡單的示例就是映射到 JNDI 搜索請求的 LDAP 搜索請求。一旦 ApacheDS 框 架了解了在處理協議請求時需要包含哪個 JNDI 操作,它就能生成事件。

MINA 中的事件處理框架 把事件傳遞給適當的處理程序。例如,如果請求需要調用 JNDI 搜索操作,那麼就調用搜索處理程序。 MINA 還維護了一個線程池。如果處理程序正忙著處理前一個操作,那麼事件會臨時保存在線程池中,直 到得到處理。

在 圖 2 中可以看到操作 JNDI 的協議提供者、MINA 接口、類以及操作處理程序。

ApacheDS 框架最大的優勢可能是它使用公共的目錄服務(JNDI)處理不同的協議提供者。這意味 著可以使用 ApacheDS 時,可以用不同的協議向客戶機公開數據。因為 ApacheDS 支持的最重要的協議是 LDAP (而且因為日後主要會把 ApacheDS 用作保存 Java 對象的 LDAP 服務器),所以我想進一步深入 討論 LDAP。

LDAP 概述

LDAP 協議定義了目錄操作的請求和響應消息。目錄操作包括把新 數據保存到目錄,搜索和檢索保存的數據,刪除不需要的數據,更新過時數據,以及類似的操作。

ApacheDS 中用來保存新數據(例如運行時 Java 對象)的 LDAP 消息叫做綁定(bind) 消息。 綁定消息把用戶數據傳輸到 LDAP 目錄服務 —— 例如 ApacheDS,並把數據保存到目錄。

LDAP 並不考慮數據存儲的物理位置。相反,LDAP 保存在 ApacheDS 中的每個數據條目指定了專 有名稱(Distinguished Name,DN)。在整個目錄服務中,每個 DN 都必須是惟一的。不允許有兩個條目 擁有相同的 DN。在本文後面將了解到 LDAP 保證每個 DN 惟一的機制。

另外,LDAP 中的搜索機 制也使用 DN。下一節介紹的示例應用程序場景將讓您熟悉 LDAP 的術語,並介紹 LDAP 的搜索機制。貫 穿這個兩部分的系列,我都將使用這個示例應用程序。

學習用的應用程序

對於應用程序的 場景,假設要為一個制造公司設計一個數據管理系統。公司有員工、客戶、合作伙伴和供應商,他們都是 數據管理系統的用戶。現在要求數據管理系統把關於用戶的數據保存在 ApacheDS 中。

系統允許 所有用戶都可以設置自己喜歡的使用系統的方式。例如,用戶可以定制在使用系統時,在個人的默認視圖 中顯示的數據,並為不同的數據元素應用不同的顯示樣式。系統還支持根據用戶類型 的特殊設置。例如 ,公司的員工(內部組織用戶)可以設置消息傳遞選項,客戶可以設置發貨選項,供應商可以設置發票選 項。

在 ApacheDS 中設置每個用戶的設置的簡單方式是以 Java 對象的形式保存選項。對於這個 應用程序場景,可以從設計一個針對所有用戶類型的 Preferences 類開始。Preferences 類包含的方法 允許用戶設置所有用戶類型(在這個示例中,是內部用戶、客戶和供應商)公共的選項。例如, Preferences 類可能包含一個 setStyles() 方法,用於指定樣式表的位置。可以用樣式表給不同的數據 元素應用顯示樣式。

也可以擴展 Preferences 類,形成 MessagingPreferences 類,用它包含針 對內部用戶的消息傳遞選項。類似地,可以為客戶設計 ShippingPreferences 類,為供應商設計 InvoicingPreferences 類。

清單 1 是 Preferences、MessagingPreferences、 ShippingPreferences 和 InvoicingPreferences 類的骨架。為簡單起見,在清單 1 中我沒有包含任何 方法(除了 setStyles() 方法)。現在我只想演示類實例在 ApacheDS 中的存儲。

清單 1. 代表 不同類型用戶的選項的 Java 類

  public class Preferences implements  java.io.Serializable {
    String styleSheetURL = null;

     public void setStyles(String styleSheetURL){
      this.styleSheetURL =  styleSheetURL;
    }
    //Other methods of the Preferences class

  }

  public class MessagingPreferences extends Preferences {
    //Methods of the MessagingPreferences class
  }

  public  class ShippingPreferences extends Preferences {
    //Methods of the  ShippingPreferences class
  }

  public class InvoicingPreferences  extends Preferences {
    //Methods of the InvoicingPreferences class
   }

用 ApacheDS 管理數據

假設 Alice 在制造公司的商務部門工作。她用數據管 理系統把她的所有數據(姓名、部門、電子郵件地址、電話號碼,等等)和她的選項(以 MessagingPreferences 對象的形式)保存到 ApacheDS 中。她保存在 ApacheDS 中的所有數據都有一個 惟一的 DN。

術 語說明

可以把 DN 當成目錄服務中的命名上下文。Alice 這類用戶的數據條目在她的 DN 定義下的命名上下文中寫入。實際上,通常會發現 DN 和命名上下文 這兩個術語被互換地使用。JNDI 文 檔通常采用命名上下文這個術語,而 LDAP 文檔則采用 DN 這個術語。如果既使用 LDAP 又使用 JNDI, 那麼可以認為這兩個術語的含義相同。

現在假設 Alice 想用數據管理系統修改她的消息傳遞選項。數據管理系統首先用 LDAP 搜索 Alice 的命名上下文,以了 解它的 DN。在知道了 DN 之後,就從 DN 提取 Alice 的 MessagingPreferences 對象,用 Alice 的最 新數據更新對象,然後把對象保存回 ApacheDS。

現在腦子裡有了一個應用程序場景,下面開始研 究如何用 ApacheDS 變化所有這些服務器端魔術。

ApacheDS 入門

要理解如何在 ApacheDS 中存儲各種類型的數據(包括 Java 對象),需要學習 LDAP 模式。而且,用圖形方式查看 LDAP 服務器 中保存的數據會有幫助,在圖形方式中可以用樹的形式查看數據。為了這個目的,我要介紹如何使用 JXplorer,這是個基於 Java 的開放源碼客戶端 LDAP 實現,為保存在 LDAP 服務器中的數據提供了浏覽 器視圖。因為我使用 JXplorer 來介紹 LDAP 模式,所以在繼續之前需要 下載和安裝 JXplorer。

如果還沒有下載 ApacheDS,那麼現在還需要 下載 ApacheDS。安裝相當簡單:會得到一個 zip 文件,解壓它得到 ApacheDS 的 JAR 文件。從命令行上,像下面這樣運行 apacheds-main-0.9.jar,啟 動 LDAP 服務器:

<JAVA_HOME>/java -jar apacheds-main-0.9.jar 

ApacheDS 的 LDAP 服務器現在在 localhost:389 上(默認端口)偵聽,准備為客戶機應 用程序的 LDAP 請求服務。

連接 ApacheDS

在啟動了 ApacheDS 之後,請運行 JXplorer, 得到圖 3 所示的浏覽器視圖。可以看到,JXplorer 還沒有連接到任何 LDAP 服務器。

圖 3. 啟 動 JXplorer 時的第一個視圖

下面,需要連接 ApacheDS。為此,使用 JXplorer File 菜單中的 Connect 命令。在連接對話框中(“Open LDAP/DSML Connection”),填寫圖 4 所示的值:

圖 4. 連接對話框

請注 意在圖 4 中,主機和端口字段指定了 ApacheDS 偵聽的地址。連接 ApacheDS 還需要用戶名和口令。 ApacheDS 自帶了默認管理用戶名(uid=admin,ou=system)和口令(“secret”)組合,可以 用它們連接 ApacheDS。請注意,我在 User DN 字段中輸入了默認用戶名,在 Password 字段中輸入了默 認口令。

在連接對話框中輸入值之後,點擊 OK。JXplorer 把連接請求發送到 ApacheDS,稍等一 會,就可以看到如圖 5 所示的屏幕。現在連接到了 ApacheDS。

圖 5. 連接到 ApacheDS 之後的 第一個 JXplorer 屏幕

ApacheDS 中的默認 數據

圖 5 中的屏幕分成兩個區,非常像 Windows 的資源管理器屏幕。左邊是一個樹形視圖,右 邊顯示樹形視圖中選中的條目的細節。

左邊有三個選項卡,分別是 Explore、Results 和 Schema 。Explore 選項卡用來尋找 ApacheDS 中包含的數據。用 Explore 選項卡來查看 ApacheDS 中的數據條 目。Results 選項卡顯示搜索結果,Schema 選項卡提供 ApacheDS 支持的模式的細節。這個討論中的大 部分地方,都將使用 Explore 和 Schema 選項卡。

請注意圖 5 顯示選中了 Explore 選項卡,它 負責提供 ApacheDS 中包含的數據的細節。因為目前在 ApacheDS 中還沒有保存任何數據,所以現在看到 的是默認數據。例如,如果點擊圖 5 中的 admin 條目,將得到圖 6 所示的屏幕,顯示 ApacheDS 自帶 的默認管理條目:

圖 6. admin 條目的細節

admin 條目代表 ApacheDS 的管理員,它的用戶名和口令在 圖 4 中輸入。圖 5 的右半邊顯示了 admin 條目的 HTML 視 圖,其中包含幾個字段,例如 User Password 字段。可以在 password 字段中輸入新口令,並點擊 Submit 按鈕,修改管理員的口令。

屬性類型的說明

圖 6 右側中的每一條目實際上都是一 個 LDAP 屬性。LDAP 定義了許多屬性類型。用 LDAP 的術語來說,屬性類型被稱作 attributeType。

屬性是為了包含數據值(例如 Common Name 字段包含的值是 ApacheDS 管理員的名稱)。對於要 保存成屬性值的數據,必須要定義它的許多方面。例如指定數據的編碼(屬性是包含文本數據還是原始二 進制數據)。

使用數據的另一個重要方面是要能夠搜索它。例如,可能想搜索與已知姓名或電子 郵件地址的用戶有關的全部數據,所以就需要指定在搜索操作中應用的匹配規則。在使用電子郵件地址時 ,可能想執行不區分大小寫的搜索。

JXplorer 可以顯示用來定義默認管理條目的屬性類型。點擊 圖 6 顯示的屏幕右側的 Table Editor 選項卡,可以看到如圖 7 所示的 Table Editor 視圖:

圖 7. admin 條目的 Table Editor 視圖

圖 7 中的表包含 “attribute type” 列和 “value” 列。可以把顯示的幾個類型映射到 圖 6 的 字段。例如,圖 7 的 cn 和 sn 屬性類型分別對應圖 6 的 Common Name 和 Surname 字段。

這 意味著數據條目中的屬性擁有與之對應的屬性類型。ApacheDS 支持眾多的屬性類型,可用於廣泛的目的 ,而且是在不同的 Internet 標准中指定的。這篇文章討論 ApachDS 支持的屬性類型的一個子集,即用 來保存 Java 對象的那些屬性類型。具體來說,我將使用 cn 屬性類型,這是個多用途屬性類型,可以用 來指定任意實體的公共名稱。可以用 cn 屬性類型指定在企業的商務部門工作的經理的姓名,也可以用它 為 Java 對象命名。可以猜得到,sn 屬性類型不屬於一般目的:它只用來指定人的姓。

ApacheDS 中的對象類

既然知道了屬性類型的一兩件事,現在來看 objectClass 屬性類型,在 圖 7 中它有 四個值:inetOrgPerson、organizationalPerson、person 和 top。這意味著 admin 條目包含四個對象 類(object class)。

實際上,ApacheDS 中的所有數據條目都使用對象類。對象類是屬性類型的 集合。如果數據條目(像 圖 6 或 圖 7 中的 admin 條目)與對象類關聯,那麼條目就在對象類中包含 所有屬性類型。

您自己可以看到 admin 條目所使用的四個對象類中包含的屬性類型。點擊 圖 7 左側的 Schema 選項卡,可以得到圖 8 所示的屏幕。Schema 選項卡顯示 ApacheDS 支持的屬性類型、對 象類和數據格式的信息。

圖 8. Schema 選項卡

現在展開圖 8 所示 屏幕左側的 objectClasses 條目。條目展開成一個長長的、按字母順序排列的列表,列出 ApacheDS 支 持的對象類型。在列表中尋找 person 對象類型,並點擊它。可以看到圖 9 所示的屏幕:

圖 9. person 對象類

定義對象類

在圖 9 中,能夠以字段的形式看到 person 對象類的細節。以下字段字義了對象類:

表 1. 定義 對象類的字段

DESC 提供 person 對象類的文本描述。person 對象類在 RFC 2256 中定義,RFC 2256 描述了 LDAP 目錄服務的客戶或用戶使用的眾多對象類和屬性類型。例如, 任何人都可能是 LDAP 服務的用戶,所以 person 對象類定義了任何人應當有的屬性(例如人的全名)。 MAY 指定 person 對象類中包含的可選屬性類型列表。例如,person 對象 類可選地包含 userPassword 和 telephoneNumber 屬性類型,它們用來容納人的口令和電話號碼。在本 文後面,我將介紹如何指定屬性類型的細節。 MUST 指定 person 對象類必 須擁有的屬性類型。person 對象類必須包含的屬性只有兩個:sn 和 cn,前面已經介紹過它們。 NAME 指定對象類的名稱。   OID 指 定對象類的對象標識符。每個 LDAP 對象類和屬性類型都必須有一個惟一的對象標識符。RFC 2256 指定 了 person 對象類的對象標識符。為了讓對象標識符惟一,Internet Assigned Numbers Authority免費 發放對象標識符。對於這篇文章來說不需要獲取對象標識符,因為我們沒有定義任何新的屬性類型。 SUP 指定對象類的雙親。對象類中的繼承概念(把雙親的能力擴展到子女) 與面向對象編程語言中的繼承類似。請注意,根據 圖 9 中的 SUP 屬性值,person 對象類擴展了名為 top 的類,這個類是所有對象類的超類。這意味著 LDAP 中的所有對象類都直接或間接地擴展了 top 對 象類。

現在來看圖 10 中顯示的 top 對象類,它只包含一個名為 objectClass 的屬性類 型。因為所有對象類都繼承自 top 類,所以不論數據條目使用什麼數據類型,在所有數據條目中,都存 在 objectClass 屬性類型。簡單來說,這意味著所有數據條目都應當定義它們使用的對象類。

圖 10. top 對象類

對象類的類型

對象類有三種類型:抽象、結構性和輔助性。了解了這點,就能注意到 top 對象類是抽象的,這 意味著它的存在只是為了讓其他對象類能夠擴展它。沒有數據條目會直接使用抽象類。

另一方面 ,person 對象類是結構性的。所有數據條目都使用結構性類。結構性類擴展其他結構性類和抽象類。例 如,叫做 organizationalPerson(在 RFC 2256 中定義)的結構性類擴展 person 對象類,後者又擴展 top 對象類。

organizationalPerson 對象類代表特殊的一類人,即在組織中工作的人。所以,它 定義了可以適用於組織中工作的人的屬性(例如,辦公室人員的工作頭銜)。圖 11 顯示了 JXplorer 屏 幕中的 organizationalPerson 對象類:

圖 11. organizationalPerson 對象類

輔助對象類是為了滿足一些非常特定的目的。這意味著輔助對象類不包含幾乎所有數據條目都 需要的通用目的屬性類型(例如前面討論的 cn 和 objectClass 屬性類型)。

數據條目不能完全 依靠輔助對象類。所以,使用輔助對象類的數據還必須使用至少一個結構性類。在本文後面,在開始介紹 如何在 ApacheDS 中保存 Java 對象時,我將提供一個輔助類的示例。

ApacheDS 中的屬性類型

現在讓我們進一步考慮 ApacheDS 中屬性類型的使用。請展開 圖 8 中所示的 JXplorer 屏幕中 的 attributeTypes 條目,它會顯示許多屬性類型。這些屬性類型是由 ApacheDS 支持的多個規范定義的 。

圖 12. ApacheDS 支持的屬性類型

點擊圖 12 所示的 cn 屬性條目,可以看到與 圖 13 所示相似的屏幕。圖 13 顯示了定義屬性類型的字段:

圖 13. cn 屬性類型

從前面對 person 對象類的討論,您已經了解了上面顯示的字段中的幾個,所以現在只討論那些還沒 了解的字段:

表 2. 更多字段

EQUALITY 指定用具體的屬性值搜 索數據條目時要應用的匹配規則。對於 cn 屬性類型,這個字段的值是 caseIgnoreMatch。使用這個屬性 類型和值意味著在使用具體名稱搜索一個人時,搜索操作不區分大小寫。 SUBSTR 與 EQUALITY 字段類似,區別是 SUBSTR 字段指定的匹配規則,針 對的是查找指定子串的搜索操作,而不是完整屬性值的搜索操作。我會在本系列的 第 2 部分 演示 SUBSTR 的影響。

還請看 圖 13 中的 SYNTAX 字段,它包含一個 OID 值。 OID 值表明屬性值的語法(或數據格式)。每個屬性類型都以屬性值的形式定義被保存的數據的語法。圖 13 中的 OID 指向的 LDAP 語法,用來在 LDAP 目錄中保存字符串。下一節討論 LDAP 語法。

ApacheDS 中的 LDAP 語法

如果點擊 JXplorer 的 Schema 選項卡,然後點擊選項卡中的 ldapSyntaxes 條目,可以看到按字母順序排列的 ApacheDSentry 中支持的 LDAP 語法列表。請找到名為 Directory String 的語法並點擊它。可以看到圖 14 所示的屏幕,顯示了定義 LDAP 語法的字段:

圖 14. Directory String 語法

Directory String 語法在 LDAP 目錄中保存字符串值。理解所有字段的含義很容易,因為它們與前面解釋過的字段相似。但 是,請注意,圖 14 中的 OID 字段與 圖 13 中的 cn 屬性的 SYNTAX 字段確切地匹配。這是因為 cn 屬 性類型遵守 Directory String LDAP 語法。這意味著 LDAP 把名稱當作字符串。

還請看圖 15, 它顯示了另一個 LDAP 語法,叫做 Octet String,它代表 8 進制字符串。Java 對象保存為 8 進制字符 串,所以在本系列文章中將使用 Octet String LDAP 語法。

圖 15. Octet String 語法


'

腦子裡有了 Directory String 和 Octet String 語法,就可以進行下一步,用 ApacheDS 制作數據條目了。

在 ApacheDS 中輸入數據

現在,已經了解了足夠的 LDAP 組 件以及如何在 ApacheDS 中實現它們以把新的數據條目寫入 ApacheDS。這個練習有助於理解模式組件( 例如對象類、屬性類型和語法)如何在 LDAP 目錄中保存或表示數據條目。

先從點擊 JXplorer Explore 選項卡開始,然後點擊選項卡中的 Users 條目。ApacheDS 沒有任何默認用戶,所以 Users 條 目為空。右擊條目,可以看到彈出菜單。在彈出菜單中選擇 New 命令,得到名為 “Set Entry Object Classes” 的對話框,如圖 16 所示:

圖 16. Set Entry Object Classes 對話框

需要做的第一件事是 在對話中提供一些信息,這些將在下一節討論。

使用專有名稱語法

正如我在討論 LDAP 模 式開始時提到過的,ApacheDS 中的所有數據都以樹的形式存在。這意味著除了根條目之外,每個數據都 擁有雙親。ApacheDS 的根條目名為 system,在 圖 16 中可以看到。

每個數據條目都擁有一個在 整個目錄中都惟一的 DN。RFC 2253提供了以字符串形式編寫 DN 的語法。根據 RFC 2253,DN 是用逗號 分隔的組件列表的形式編寫的,每個組件都有自己的值。雖然可以用多個組件定義一個 DN,但我在本文 中只使用三個組件:ou、uid 和 cn。每個組件都有自己的目的:

ou 組件指定組織單元的名稱。 對於本文,可以想像它實際是數據組織單元的名稱。用這個屬性可以在 ApacheDS 中構建不同類型的數據 。

uid 組件提供條目的用戶標識符。正常情況下,用這個屬性標識 ApacheDS 的用戶(例如 Alice)。

cn 組件命名 Java 對象。

圖 16 中所示的根條目 system 的 DN 是 ou=system 。“users” 條目是 system 的直接孩子,所以 user 的 DN 是 ou=users,ou=system。請注 意 user 的 DN 的第一部分(ou=users)叫做它的相對專有名稱(RDN)。

創建 RDN 條目

子條目(例如 ou=users)的 RDN 前面要加上雙親的 DN (例如 ou=system),中間用逗號分隔,從而構 成子條目的 DN(例如 ou=users,ou=system)。同一雙親的兩個相鄰孩子(即兄弟)不會有相同的 RDN。 這就保證了在整個 LDAP 目錄中 DN 都是惟一的。

記住了這一點,就可以容易地理解 圖 16 所示 的 Parent DN 和 Enter RDN 字段的含義了。在創建新條目時,右擊 Users 條目,出現 Parent DN 字段 ,裡面已經填充了 Users 條目的 DN。

下一步是提供想要創建的條目的 RDN。對於示例應用程序 ,要創建名為 Alice 的新用戶,所以在 圖 16 的 Enter RDN 字段中輸入 uid=Alice 。這就形成了 Alice 條目的 DN uid=alice,ou=users,ou=system。

請注意對於專有名稱的數據查詢或搜索操作 (我將在本系列的第 2 部分演示)是不區分大小寫的。這意味著從實踐上看,指定 uid=Alice 或 uid=alice 作為 RDN 字段的值是沒有區別的。

使用對象類

迄今為止都還不錯。下面,選 擇新條目要使用的對象類。可以為一個條目選擇任意數量的對象類。在選擇對象類時,需要提供具體對象 類中包含的所有必需屬性。另外,還要提供對象類的可選屬性。

應當記得 Alice 在數據管理系統 的目標公司的商務部門工作,所以她只需要屬於 organizationalPerson 對象類的屬性,這些屬性我在 圖 11 中介紹了。所以,請把 organizationalPerson 對象類加入 圖 16 所示的 Selected Classes 列 表,並點擊 OK。

請看圖 17 的屏幕,其中在 Set Entry Object Classes 對話框之後顯示了 Alice 條目。請注意圖 17 中 Alice 的 uid 值(剛剛輸入的)用藍色顯示:

圖 17. Alice 條 目顯示在 Set Entry Object Classes 對話框之後

應用屬性值

下 面,需要提供必需屬性的值(cn 和 sn 屬性,在 圖 15 中以黑體顯示),並點擊 Submit。然後, JXplorer 就會制作一個 LDAP 請求,形成一個新條目,並把請求發送給 ApacheDS。

ApacheDS 把 確認響應消息發送回 JXplorer,JXplorer 更新數據樹,如 圖 16 所示。在圖 18 的右側可以看到生成 的名為 Alice 的條目:

圖 18. Alice 的條目

出現這個條目,就證 明完成了。已經用 ApacheDS 完成了第一個數據條目!

Java 序列化和 RMI

只要想把 Java 對象保存在目錄中,要做的第一件事就是把 Java 對象轉換成字節表示形式。這種轉換過程叫做序列化。 序列化過程的輸出是一個字節流,字節流可以通過網絡傳遞給 ApacheDS,然後在 ApacheDS 中保存為 Java 對象的字節表示。

遠程方法調用(Remote Method Invocation,RMI)用特殊的方式利用序 列化過程。在討論把 Java 對象保存在 ApacheDS 的具體細節之前,先要確保理解其中包含的概念基礎。

序列化 Java 對象

Java 語言有一個規范,叫做 Java Object Serialization Specification version 1.5,這個規范定義了把 Java 對象轉換成字節流的過程。根據 Java Object Serialization 規范,序列化 Java 對象的過程已經在 JRE 中以序列化運行時的形式實現了,序列化運 行時處理 Java 對象的序列化和反序列化。

定 制序列化

如果應用程序的架構不允許數據成員被序列化(例如,某個數據成員屬於現有的 非序列化類),那就需要在想要序列化的 Java 類中實現自己的定制序列化和反序列化邏輯。

序列化運行時包含兩個方法:writeObject() 和 readObject()。序列化運行時根據 Java Object Serialization 規范,用它們序列化和反序列化 Java 對象。想要序列化的 Java 對象只需要實現叫做 java.io.Serializable 的接口。Serializable 接口不 包含任何方法。它的作用只是告訴序列化運行時這個對象是可以序列化的。

請注意序列化運行時 會在序列化過程中把 Java 對象的數據成員序列化。如果某些數據成員本身還是另外的 Java 對象,那麼 需要與想要序列化的主對象一起序列化這個成員。所以,這類數據成員也應當實現 Serializable 接口。

在本系列的第 2 部分,我將演示如何用 Java 中默認的序列化支持來在 ApacheDS 中保存 Java 對象。

RMI

除了序列化對象,可能想在通過網絡發送字節表示之前,在它上面應用一些特 定的編碼方案。這個編碼過程叫做編組(marshalling),它是 Java RMI 規范的重要元素。RMI 框架允 許 Java 應用程序使用遠程對象。遠程對象位於 Java 應用程序的范圍之外,例如 Internet 上。

使用 RMI,可以像調用本地對象的方法一樣調用遠程對象的方法。要做到這點,需要一個遠程對 象的存根類。存根類包含遠程對象的方法簽名。應用程序實例化存根類並在本地調用它的方法。然後 RMI 框架管理與遠程對象的通信,形成對所需方法的遠程調用。結果是,應用程序不需要了解對象實際上是在 本地還是遠程。

對這個討論有意義的內容是(您可能猜得到) RMI 框架允許 Java 對象在網絡上傳遞,調用遠程對象 的方法。所以,RMI 需要序列化 Java 對象。RMI 規范指定編組算法,並把算法應用到 Java 對象的序列 化形式上。算法會在序列化的對象上插入特殊標志。

RMI 規范在 J2SE 中已經實現,所以不需要 擔心對象編組的低層細節。只要使用 RMI 類編組 Java 對象即可。LDAP 允許把編組的 Java 對象保存在 LDAP 目錄。在本系列的第 2 部分,我將演示如何編組 Java 對象和取消編組,以及如何在 ApacheDS 中 保存和檢索它們。

把 Java 對象保存在 ApacheDS

在本系列的第 2 部分中,我要介紹一個 簡單的應用程序,這個程序包含目前學到的所有概念。我將介紹如何表示序列化的 Java 對象,如何使用 不同的對象類,如何表示編組的 Java 對象,如何把 Java 對象引用保存在 ApacheDS 中。在 第 2 部分 中,我將在這些簡單練習上再進一步。但是現在,只需把注意力放在包含的基本步驟上。

開始時 ,需要一套要處理的對象類。RFC 2713定義了在 LDAP 目錄中表示 Java 對象的對象類和屬性類型。 ApacheDS 對這些屬性類型和對象類提供了完整支持。在這個練習和第 2 部分的練習中,我使用了四個對 象類:javaContainer、javaObject、javaSerializedObject 和 javaNamingReference。現在來看前兩個 對象類和它們的屬性。

javaContainer(如圖 19 所示)是個構造性類,只包含一個屬性: cn。 這個對象類的目的是命名包含 Java 對象的數據條目。LDAP 允許使用另一個結構性對象類給 Java 對象 命名。例如,也可以用 person 對象類保存 Java 對象。

圖 19. javaContainer 類

javaObject 是個抽象類。這個對象類的目的是定義一些輔助屬性,這些屬性在保存 Java 對象 的數據時不是直接有用,但是從目錄進行搜索或檢索對象的搜索操作時會有幫助。圖 20 顯示了 javaObject 類:

圖 20. javaObject 類

圖 20 中顯示的 javaObject 類中的屬性類型如下所示:

一個必需的屬性類型,名為 javaClassName,它容納保存 在 ApacheDS 中的實例所屬的類的名稱。通常用這個屬性查找在 ApacheDS 中保存的具體類的實例。

另一個名為 javaClassNames 的屬性類型容納 Java 對象的所有超類以及對象實現的所有接口的 名稱。這個屬性會包含大量的值,所以是一個多值屬性類型。LDAP 允許用多值屬性容納多個值。可以用 javaClassNames 屬性類型搜索實現特定接口的對象或者擴展特定類的對象。

圖 20 中顯示的 javaCodebase 屬性類型保存 Java 對象的類定義所在的位置。這是個可選屬性,如果應用程序需要從 ApacheDS 讀取類的位置以便裝入類定義的時候才用這個屬性。

javaDoc 屬性類型也是可選的,容 納 ApacheDS 中保存的類實例所屬的類的 Java 文檔的 URL。

可以猜到,description 屬性類型 保存類的文本描述。

代表序列化的 Java 對象

請注意,屬性類型 javaObject 中沒有一個 屬性類型保存代表被保存對象的實際八進制字符串。這就是為什麼 javaObject 類保持抽象的原因,也是 為什麼不能直接用它創建數據條目的原因。LDAP 用這種方式定義 javaObject 類,是因為 LDAP 允許用 不同形式保存 Java 對象(例如,序列化形式的對象或編組形式的對象)。每種對象代表形式都有自己的 對象類,擴展自 javaObject 類。

名為 javaSerializedObject 的對象類(圖 21 所示)擴展了 javaObject 類,只添加了一個叫做 javaSerializedData 的屬性。javaSerializedData 屬性包含 Java 對象實際的序列化形式。

圖 21 顯示的 javaSerializedObject 類是個輔助對象類,至於原因馬 上就會解釋:

圖 21. javaSerializedObject 類

現在請看圖 22,這 是一個叫做 MessagingPreferences 的序列化 Java 對象,保存在 ApacheDS,如 JXplorer 的屏幕所示 :

圖 22. 保存在 ApacheDS 中的 Alice 的 MessagingPreferences 對象

圖 22 中的 MessagingPreferences 對象代表用戶 Alice 想使用的選項設置。這是 MessagingPreferences 對 象看起來是 Alice 數據條目對象(在本文前面創建的)的子對象的原因。

使用不同的對象類

如圖 22 所示,MessagingPreferences 數據條目對象使用四個對象類:javaSerializedObject、 javaObject、javaContainer 和 top。您能猜出 MessagingPreferences 對象為什麼需要這四個類麼?

MessagingPreferences 數據條目對象需要 javaSerializedObject 類的原因是要保存 MessagingPreferences 對象的序列化形式。

需要 javaObject 類是因為 javaSerializedObject 類擴展了 javaObject 類。這意味著只要數據條目對象使用 javaSerializedObject 類,也就會使用 javaObject 類。

需要 javaContainer 類是因為其他三個對象類(javaSerializedObject、 javaObject 和 top)都不是結構性類。ApacheDS 中的每個數據條目對象都需要使用一個結構性類。Java 對象可以使用 javaContainer 或其他任何結構性類(例如 person 對象類)。LDAP 希望把 Java 對象條 目與結構性類(像 javaContainer 或 person 對象類)混合,所以 LDAP 規范把 javaSerializedObject 類定義成輔助類。

最後,MessagingPreferences 數據條目對象需要 top 類是因為所有對象類都 擴展自 top 類,如我前面解釋的。

表示編組的 Java 對象

現在看圖 23,圖中顯示了 ApacheDS 中保存的編組 Java 對象:

圖 23. ApacheDS 中保存的編組對象

可以 比較圖 23 和 圖 22(圖 22 在 JXplorer 屏幕中顯示序列化對象)。圖 23 中的 javaClassName 屬性 顯示了包含 java.rmi.MarshalledObject 類的實例的條目。在本系列的第 2 部分,我將用這個類演示 Java 對象編組。

保存 Java 對象的引用

最後,LDAP 還允許在目錄中保存 Java 對象的引 用 而不是實際的對象。在這種情況下,把 Java 對象的地址保存在 ApacheDS 中。在取消地址引用以獲 得對象實例時,需要工廠對象。工廠對象實現取消引用邏輯。

保存引用的主要優勢是在不同用戶 之間共享對象。例如,回想一下我在前面的討論中與 清單 1 一起介紹的 MessagingPreferences 類。如 果多個用戶共享共同的消息傳遞選項,就會發現保存一個表示 MessagingPreferences 公共選項的實例, 然後為使用選項的每個人保存一個引用是有好處的。

RFC 2713 有一個名為 javaNamingReference 的對象類(圖 24 所示),它擴展了 javaObject 類,並定義了兩個新屬性:javaReferenceAddress 和 javaFactory。javaReferenceAddress 屬性類型保存 Java 對象的引用(或地址),而 javaFactory 屬 性類型保存工廠對象的名稱。

圖 24. javaNamingReference 類

第 1 部分結束語

在介紹把 Java 對象保存到 ApacheDS 中的系列文章的第 1 部分,您學習了很多 ApacheDS 中關於可插入協議的支持。還學習了核心 LDAP 概念和術語,包括專有名稱、對象類、屬性類 型和 LDAP 語法。最後,學習了如何用這些 LDAP 概念在 ApacheDS 中表示和保存 Java 對象。

在本系列的第 2 部分,將把這些概念放在一起測試。我包含了幾個示例 Java 應用程序和許多 Java 代 碼,以演示如何在 ApacheDS 中保存、搜索和檢索 Java 對象。示例應用程序實現了這裡介紹的數據管理 場景的各個方面。在結束第 2 部分之前,我還利用可以用在您自己的應用程序中的可重用 Java 類的形 式總結了相關概念。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved