JNDI基礎

Java命名和目錄接口

原文地址: https://docs.oracle.com/javase/tutorial/jndi/TOC.html

Naming Concepts

命名服務:通過名字讓不同的對象進行聯繫
當我們發送郵件時,系統就是通過我們提供的郵箱地址去尋找對應的一個系統對象
這裏寫圖片描述
Naming的主要功能就是把一個簡單的名字映射到一個複雜的對象
例如:DNS映射
www.baidu.com ==> 61.135.169.125
系統文件映射:
c:\bin\autoexec.bat ==> File Reference
從上面兩個例子中就可以看出命名服務在我們生活中的廣泛應用.

Names

命名系統的名稱必須遵循相應的系統語法:一個名稱代表一個組件,不同的組件進行關聯需要使用約定的規則,下圖是利用分隔符關聯
這裏寫圖片描述
unix系統中,路徑使用”/”分開,”/”左右代表不同的目錄(文件)
DNS使用”.” 來關聯
Lightweight Directory Access Protocol (LDAP)使用 “,”分割不同的組件,每個組件使用”=”分割名字和值

Bindings

綁定:一個名稱與對象關聯
一個文件名綁定一個文件,一個域名綁定一個ip地址,一個 LDAP名字綁定一個LDAP實體…

References and Addresses

根據命名服務,某些對象不能直接被命名服務存儲,也就是說,一個對象的副本不能放置在命名服務中。相反,它們必須被引用存儲;也就是說,一個指向對象的指針或引用被放置在命名服務中,一個引用代表有關如何訪問對象的信息。通常,它是一個緊湊的表示,可以用來與對象進行通信,而對象本身可能包含更多的狀態信息。

Context

一個Context就是一組名字和對象的綁定集合,每一個Context都有自己的命名規則.一個Context提供一個搜索功能從而返回一個綁定對象,Context通常也提供綁定名字~解綁名字~列出綁定名字的功能.一個Context中的對象也可以綁定另外一個Context的對象(稱爲subcontext),但是他們要具有相同的命名規則.
這裏寫圖片描述
Unix中的每個文件目錄,都在Unix的Context中,一個文件目錄(sub)可以相對另一個文件目錄(parent)命名來表示一個子目錄,這個bin目錄就是usr的subcontext.

Naming Systems and Namespaces

命名系統是一個連接相同類型的Context集合(它們具有相同的命名規則),並且有一組共同的操作.
命名系統爲其客戶端提供命名服務,用於執行命名相關操作。通過它自己的接口訪問命名服務。
命名空間是一個命名系統中所有可能的名字的集合。

Directory Concepts

許多命名服務擴展到一個目錄服務。目錄服務將名稱與對象關聯,還可以與這些對象的屬性關聯
目錄服務 =命名服務+對象(目錄對象)
你不僅可以用它的名字查找某個對象,還可以獲取對象的屬性或基於它的屬性搜索對象。
這裏寫圖片描述
舉一個電話薄的目錄服務,一個用戶名可以映射到一個人,一個人擁有地址~手機號~郵箱…屬性信息,這裏人就是一個目錄對象,在這個目錄對象裏面可以存儲很多信息(屬性),這些信息都可以通過人的名字獲取到.
Directory Object : 目錄對象包含許多屬性用來描述它自己

Attributes

    目錄對象可以包含許多屬性

Directories and Directory Services

目錄是一組連接的目錄對象
目錄服務是提供 創建、添加、刪除和修改與目錄中對象相關聯的屬性操作。並通過自己的接口訪問服務。

Search Service

向目錄服務提供名稱得到一個目錄對象,另外,還有一些目錄,例如LDAP是支持搜索感念的,當你去搜索一個目錄對象,可以使用一個名字也可以使用一個邏輯表達式來指明目錄對象的屬性去獲取對象.這種搜索稱爲搜索過濾器.這種風格的搜索有時被稱爲反向查找或基於內容的搜索。目錄服務搜索會返回滿足搜索篩選器的對象.
  • Combining Naming and Directory Services
    目錄時常安排他們的對象形成一個層次結構,例如LDAP目錄中所有的對象都組成一個樹形結構,稱爲目錄信息樹(directory information tree (DIT)).在這個DIT裏面,一個組織對象可能包含組對象也可能包含個人對象,當目錄對象被安排在這種方式中時,它們在容器的屬性中又可以作爲一個Context。

JNDI

Java命名和目錄接口™(JNDI)是一個應用程序編程接口(API),提供命名和目錄的功能。它被定義爲獨立於任何特定目錄服務的實現,因此任何一個已經部署的目錄服務都可以使用一種共同的方式訪問。

Architecture

JNDI架構包括一個API和服務提供者接口(SPI),Java應用程序使用JNDI API來訪問各種命名和目錄服務。SPI使各種命名和目錄服務暴漏出來,透明化,從而允許Java應用程序使用JNDI API來訪問他們的服務。見下圖
這裏寫圖片描述

Packaging

Java SE平臺包含JNDI。使用JNDI,你必須有JNDI類和一個或多個服務提供者。JDK包括以下命名和目錄服務的服務提供商:
- Lightweight Directory Access Protocol (LDAP) (輕量級目錄訪問協議)
- Common Object Request Broker Architecture (CORBA) Common Object Services (COS) name service (公共對象請求代理體系結構)
- Java Remote Method Invocation (RMI) Registry(java遠程方法調用)
- Domain Name Service (DNS)
JNDI劃分在五個包中:
- javax.naming
- javax.naming.directory
- javax.naming.ldap
- javax.naming.event
- javax.naming.spi

Naming Package

java.naming包含了訪問命名服務的類和接口.

Context

java.naming.Context接口是一個提供搜索/綁定/解綁,重命名對象/創建/銷燬subcontext的核心接口

  • Lookup:
    lookup(Name/String):最常用的搜索操作,傳入一個你想要搜索的名稱,它會返回一個綁定在該名稱的一個對象.
  • Bindings:
    listBindings(Name/String)返回一個按照name-to-object綁定的枚舉集合,綁定包含了對象名稱/對象類名稱/對象本身
  • List:
    list(Name/String)和listBinding相似,只不過它返回一個包含對象名稱/對象類名稱的枚舉集合,不包含對象本身.這個list方法有時是一個很有用的操作,當你只想瀏覽對象的一些信息而不包含對象本身時,它將比listBinding更有效率,代價更低
  • Name:
    Name是表示一個通用名稱的接口,一個擁有零或多個組件的有序序列.命名系統使用此接口來定義遵循其在命名和目錄概念中所描述的約定名稱
  • References:
    對象以不同的方式存儲在命名和目錄服務中。一個對象的引用可能是一個非常簡潔的表示.JNDI使用Reference類來表示引用,一個引用包含如何構造對象的副本,JNDI會嘗試尋找在目錄服務中的java對象並將其轉化爲Reference.這樣JNDI客戶端就會有一種錯覺:任何java對象都可以存儲在目錄服務中.

The Initial Context

在JNDI中所有的命名和目錄操作都是相對於Context.沒有絕對的根路徑,因此JNDI聲明一個InitialContext,它提供一個開始的指針以便於命名和目錄的操作,一旦你擁有了一個InitialContext,你將依賴於它尋找其他的Context和對象.

Exceptions.

JNDI定義了一個具有層次結構的異常機制,能夠處理命名和目錄操作的任何錯誤.這個異常機制的根是 NamingException.

Directory Package

javax.naming.directory包繼承javax.naming包提供了訪問目錄服務但不包含命名服務的功能。這個包允許應用程序來檢索存儲在目錄中的對象,並使用指定的屬性來搜索對象.

  • The Directory Context

javax.naming.directory.DirContext接口代表一個目錄的Context。DirContext通過繼承javax.naming.Context也能作爲一個命名Context。這意味着任何目錄對象還可以提供命名Context。它定義了用於檢查和更新目錄入口的屬性的方法。

  • Attributes

你用getattributes()方法檢索與目錄項關聯的屬性(爲你提供的名稱)。使用modifyattributes()修改屬性。可以添加、替換或刪除屬性以及屬性值。

  • Searches

DirContext 包含基於目錄的搜索方法。最簡單和最常見的用法,應用程序提供一組符合指定屬性的value給search()方法搜索目標對象。其他重載search()的方法能支持更復雜的搜索過濾。

LDAP Package

javax.naming.ldap覆蓋了javax.naming.directory並提供LDAP V3特有的的功能類和接口。事實上,大多數應用程序使用javax.naming.directory包足夠找到LDAP,而不需要使用javax.naming.ldap包。此包主要用於那些需要使用”extended” operations, controls, unsolicited notifications.

  • “Extended” Operation
    除了一些明確的操作,如搜索和修改,LDAP V3(RFC 2251)指定一種方式傳遞尚未定義的操作在LDAP客戶機和服務器之間。這些操作被稱爲“擴展”操作。“擴展”的操作可以由一個標準組織,如因特網工程任務組(IETF)定義或由供應商。
  • Controls
    LDAP V3允許任何請求或響應未定義的修改器。一個控件發送一個請求是一個請求控件,一個控件發送一個響應是一個響應控件。一個控件可能由一個標準組織定義,如“Internet工程任務組(IETF)或通過一個供應商。請求控件和響應控件不是必須成對存在的,也就是說,不需要爲每個請求控件發送一個響應控件,反之亦然。
  • Unsolicited Notifications
    除了客戶端和服務器之間的交互的正常請求/響應方式,LDAP V3還提供了不請自來的通知消息—從服務器異步發送到客戶端而不需要任何請求。

The LDAP Context

LdapContext接口是一個可進行擴展操作的Context.發送請求控件/接收響應控件.

Event Package

javax.naming.event包含了支持命名和目錄服務事件通知的類和接口.

  • Events
    NamingEvent是由一個命名/目錄服務生成的事件。事件包含事件類型。例如,有些事件類型能夠影響命名空間的事件,例如“對象添加”,而另外一些則不能,比如“對象更改”。

  • Listeners
    NamingListener是一個監聽NamingEvent的對象,每一個類型的NamingEvent都有一個NamingListener與其對應.例如,一個NamespaceChangeListener用來監聽命名空間更改的事件,一個ObjectChangeListener用來監聽對象更改的事件。

    接受時間通知,要求listener必須註冊一個 EventContext 或者EventDirContext.一旦註冊,當相應的更改發生在命名/目錄服務時,該偵聽器將接收事件通知.
    

Service Provider Package

javax.naming.spi包的作用是適配不同的命名和目錄服務,任何服務都可以通過JNDI進入應用。
- Plug-In Architecture
javax.naming.spi允許不同的實現動態插入,這些實現包括那些 initial context 和contexts .

  • Java Object Support
    javax.naming.spi:可以執行lookup()返回自然和直觀的Java對象.例如,如果你從目錄中查找打印機名稱,那麼你可能會希望得到一個可以操作的打印機對象。這種支持是以對象工廠的形式提供的。
    該包還提供了反向操作。那就是 Context.bind()可以接受Java對象並存儲對象到底層的命名/目錄服務。這種支持是以靜態工廠的形式提供的。

  • Multiple Naming Systems (Federation)
    JNDI操作允許應用程序提供名字,跨越多個命名系統。在完成一個操作過程中,一個服務提供者可能需要與另一個服務提供者進行交互.

Software Setup

Required Software

需要下面的軟件和系統:
Java platform software
Service provider software
Naming and directory server software

Java Platform Software

JNDI包含再JAVA SE的平臺中.
運行JNDI,你可以使用任何兼容Java的Web瀏覽器,如Firefox或Internet Explorer V5或後。確保你的應用程序充分利用了Java平臺軟件的最新功能,您可以使用Java插件與瀏覽器

Service Provider Software

JNDI API是一個通用的API用來訪問任何命名和目錄服務。實際上訪問命名和目錄服務是在一個服務提供商的JNDI中。
一個服務提供商的軟件,去映射JNDI API實際調用的命名和目錄服務器。通常,服務提供者和命名/目錄服務器的角色不同。在客戶機/服務器軟件的術語中,JNDI和服務提供者是客戶端(稱爲JNDI客戶端),命名和目錄服務器是服務器。
客戶端和服務器可以在很多方面進行交互。有一個共同的方式,他們使用網絡協議,使客戶端和服務器可以在一個網絡環境中存在的,服務器通常支持許多不同的客戶端,不僅提供JNDI客戶,只要客戶端符合指定的協議即可。JNDI不指定任何特定風格的JNDI客戶端和服務器之間的交互。例如,在一個極端的客戶端和服務器可以是相同的實體。
您需要獲得您將使用的服務供應商的類。例如,如果你計劃使用JNDI訪問LDAP目錄服務器,那麼你就需要一個LDAP服務提供商提供的軟件.
JDK自帶的服務提供商:

  • Light Weight Directory Protocol (LDAP)
  • CORBA Common Object Services naming (COS naming)
  • RMI registry
  • Domain Name Service (DNS)

如果你感興趣其他供應商的服務: http://www.oracle.com/technetwork/java/jndi/index.html
本次只使用LDAP服務提供商。使用LDAP服務提供商時,你需要建立自己的服務器或訪問一個已經存在的服務器.

Naming and Directory Server Software

一旦你獲得了服務提供商的軟件,你需要設置或訪問一個相應的命名/目錄服務器.設置命名/目錄服務器通常是網絡系統管理員的工作。不同的供應商有不同的安裝程序爲他們的命名/目錄服務器。一些在服務器安裝前需要特殊的機器權限。你應該查閱命名/目錄服務器軟件的安裝說明。
本目錄的例子,你需要訪問LDAP服務器。如果你想以一個快速遊覽什麼LDAP來看看。你可以使用任何你選擇的符合LDAP服務器。甲骨文目錄服務器,它運行在許多平臺上,包括窗口,http://www.oracle.com/technetwork/testcontent/index-085178.html
你也可以下載免費的LDAP服務器:

一個公開的服務器: ldap://ldap.openldap.org .Naming Context: dc=OpenLDAP,dc=org

LDAP Setup

下面是用java應用搭建一個LDAP Directory Server的步驟:
1.安裝java平臺
2.獲取目錄服務器軟件,如前面討論過的。
3.使用所需模式配置目錄服務器。(本次示例在服務器上配置了一個特殊的架構)
4.用期望的內容填充目錄服務器。(本次示例中一個特殊的內容需在服務器上填充)
5.寫一個JNDI應用程序去訪問目錄,編譯並運行它對目錄服務器到你想要的結果。
目錄可以被看作是由名稱到對象綁定的。也就是說,每個目錄中的每個對象都有一個對應的名字。你可以在目錄中檢索它的名字。
還存儲在目錄中的屬性。目錄中的一個對象,除了具有名稱外,還具有一個可選的屬性集。你可以尋找一個對象的屬性通過目錄,以及尋找一個具有某些屬性的對象通過目錄。

Directory Schema

Schema指定一個目錄可能包含的對象類型。本文的示例要求一些特殊的Schema定義,去填充目錄實體,所以需要使用兩個文件

Providing Directory Content for This Tutorial

在這個例子中,顯示的結果反映了LDAP目錄已使用配置文件設置(tutorial.ldif:https://docs.oracle.com/javase/tutorial/jndi/software/config/tutorial.ldif)。如果您正在使用一個現有的服務器,或者使用不同的設置服務器,那麼您可能會看到不同的結果。在你可以加載配置文件(tutorial.ldif)到目錄服務器,您必須遵循更新服務器的Schema或者如果你的是UNIX系統要使用ldapadd命令或ldapmodify。
例如,你可以使用ldapmodify(替換主機名,管理員DN(-D選項)和密碼):

ldapmodify -a -c -v -h hostname -p 389\
        -D "cn=Administrator, cn=users, dc=xxx, dc=xxx"\
        -w passwd -f tutorial.ldif
      - Installation Note: Access Control.

不同目錄服務器的訪問控制不同。一些例子對目錄進行更新。另外,在安裝本文的命名空間中,可能有讀訪問權限的部分。因此,你需要採取具體行動使服務器目錄的可讀性或更新爲示例工作。對於Oracle目錄服務器(http://www.oracle.com/technetwork/testcontent/index-085178.html)添加在sunds.aci.ldif: (https://docs.oracle.com/javase/tutorial/jndi/software/config/sunds.aci.ldif)文件建議DN ACI輸入:o=JNDITutorial使整個目錄可讀和可更新。或者,您可以更改示例,以使它們對目錄進行身份驗證。

  • Installation Note: Namespace Setup.
    在tutorial.ldif文件條目使用專有名稱(DN)“O = jnditutorial”爲根命名上下文。如果你沒有配置你的服務器有“O = jnditutorial”作爲Context的根,然後你試圖進入tutorial.ldif會失敗。爲了解決這個問題最簡單的方法是添加一個現有的根命名Context的DN dn:到每個tutorial.ldif文件開頭。例如,如果你的服務器已經有根命名Context:”dc=imc,dc=org”.那麼你應該修改:
dn: o=JNDITutorial
to
dn: o=JNDITutorial, dc=imc, dc=org

在文件每行開頭的改變爲這種:”dn:”.然後,在所有的例子在本文中,任何採用”o=JNDITutorial”,用”o=JNDITutorial,dc=imc,dc=org”代替。

  • Installation Note: File Format
    根據你使用不同的操作系統平臺,你可能需要編輯tutorial.ldif以便它包含平臺正確的換行符。例如,如果你發現tutorial.ldif包含Windows風格的換行符(CRLF回車換行)與您正在導入這個文件到一個是在UNIX平臺上運行的目錄服務器,那麼你需要編輯這個文件,CRLF更換爲LF。此問題的症狀是,目錄服務器拒絕所有的條目tutorial.ldif。
  • Installation Note: Windows Active Directory
    1.根命名Context不會是 “o=jnditutorial”.將是”dc=x,dc=y,dc=z”.您需要遵循先前的Namespace Setup設置說明。
    2.添加對象類和相關的屬性“inetOrgPerson”和“GroupOfUniqueNames對象類到Active Directory Schema中,使用ActiveDirectory管理控制檯,ADSIEdit管理.”groupOfUniqueNames”是在RFC 2256中定義, “inetOrgPerson”在RFC 2798。
    3.在 Active Directory中,默認情況下,不允許使用該指南的分層關係。爲了使這些關係,利用Active Directory Management Console snap-in, ADSIEdit添加它們.

    objectclass: organizationalUnit
    possible superiors: domainDNS
    inetOrgPerson
    organizaton
    organizationalPerson
    organizationalUnit
    person
    top
    objectclass: groupOfUniqueNames
    possible superiors: top
    objectclass: inetOrgPerson
    possible superiors: container
    organizationalPerson
    person
    top

4.刪除一個 “sn”屬性從tutorial.ldif的Mark Twain實體。Active Directory定義 “sn” 是一個單值屬性,相反,RFC 2256。
5.使用Ldifde命令修改tutorial.ldif文件。

\# ldifde -i -v -k -f tutorial.ldif

6.大多數的例子假定目錄已設置允許未經身份驗證的訪問讀取和更新。您的活動目錄設置可能不允許您這樣做。查看訪問控制安裝說明。
7.讀一個條目有時會產生更多的屬性,而不是顯示在本教程中,因爲活動目錄經常返回一些內部屬性。
8.創建的條目可能需要額外的活動目錄的具體屬性或使用其他對象類的規範。

Java Application Setup

在你的程序中使用JNDI,你需要建立它的編譯和執行環境。

Importing the JNDI Classes

以下是JNDI包:
javax.naming

javax.naming.directory
javax.naming.event
javax.naming.ldap
javax.naming.spi

在這個例子中使用的類和接口的前兩個包。你需要將這2個包導入到你的程序中,或者導入你使用的單獨的類和接口。下面兩行表示導入這兩個包javax.naming和javax.naming.directory的所有類和接口。
import javax.naming.*;
import javax.naming.directory.*;

Compilation Environment

編譯一個程序使用JNDI,您需要訪問JNDI類。在Java SE 6已包括JNDI類,所以如果你使用它,你不需要採取進一步的行動。

Execution Environment

使用JNDI運行一個程序,你需要程序使用JNDI類和任何服務提供商的類。 Java Runtime Environment (JRE) 6已包括JNDI類和服務商的LDAP,COS 命名,RMI註冊表和DNS。
如果你使用的是其他一些服務商,那麼你需要下載並在JAVA_HOME/jre/lib/ext目錄安裝他們的存檔文件,其中 JAVA_HOME是包含JRE的目錄。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章