您的位置:首页 > 其它

JNDI基础

2015-08-14 18:05 330 查看

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服务器:

OpenDS: http://opends.java.net/

OpenLDAP:http://www.openldap.org/

Fedora Directory Server:http://directory.fedoraproject.org/wiki/Main_Page

Apache Directory Server:http://directory.apache.org/

一个公开的服务器: 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定义,去填充目录实体,所以需要使用两个文件

Schema for Java objects: https://docs.oracle.com/javase/tutorial/jndi/software/config/java.schema

Schema for CORBA objects: https://docs.oracle.com/javase/tutorial/jndi/software/config/corba.schema

不同目录服务器有不同的配置模式。本文有安装Java和CORBA架构到目录服务器的工具,工具允许他们的Schema通过 LDAP修改。下面是一个可以执行列表:

Create Java Schema: https://docs.oracle.com/javase/tutorial/jndi/software/config/CreateJavaSchema.java

Create CORBA Schema: https://docs.oracle.com/javase/tutorial/jndi/software/config/CreateCorbaSchema.java

按照这个文件安装: https://docs.oracle.com/javase/tutorial/jndi/software/config/README-SCHEMA.TXT

注意:Windows活动目录。活动目录使用内部格式管理它的Schema。更新Schema,你可以使用Active Directory管理控制台管理单元,ADSIEdit,或createjavaschema工具,以下为活动目录的说明。

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的目录。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: