public interface Context
此接口表示一个命名上下文,它由一组名称到对象的绑定组成。它包含检查和更新这些绑定的一些方法。
每个作为参数传递给 Context 方法的名称都是相对于该上下文的。空名称用于命名上下文本身。名称参数绝对不能为 null。
大多数方法具有重载形式,一种带有 Name
参数,另一种带有 String
参数。这些重载的方法是等效的:如果 Name
和 String
参数只是相同名称的不同表示形式,则相同方法的重载形式的行为也相同。在以下方法描述中,仅完整记录一种形式。第二种形式将链接到第一种:对两者应用相同的文档。
对于支持联合的系统,Context 方法的 String 名称参数是复合名称。是 CompositeName 实例的那些名称参数被视为复合名称,而不是 CompositeName 实例的 Name 参数被视为组合名称(可能是 CompoundName 实例或组合名称的其他实现)。这允许将 NameParser.parse() 的结果用作 Context 方法的参数。在 JNDI 1.2 之前,所有名称参数都被视为复合名称。
此外,对于支持联合的系统,NamingEnumeration 中所有从 list() 和 listBindings() 返回的名称都是表示为字符串的复合名称。有关名称的字符串语法,请参见 CompositeName 。
对于不支持联合的系统,名称参数(Name 或 String 形式)和 NamingEnumeration 中返回的名称可能是其自己的名称空间中的名称,而不是复合名称空间中的名称,这由服务提供程序决定。
此接口中的所有方法都可以抛出 NamingException 或其任意子类。有关每个异常的详细信息,请参见 NamingException 及其子类。
不保证 Context 实例与多个线程的并发访问是同步的。需要并发地访问单个 Context 实例的线程应该在它们之间实现同步并提供必需的锁定。对于每个线程都操作一个不同 Context 实例的多个线程而言,无需实现同步。注意,向 lookup
方法传递空名称将返回一个表示相同命名上下文的新 Context 实例。
为了实现并发控制,返回 NamingEnumeration 的 Context 操作在枚举仍在使用中或者仍在遵从该操作生成的所有反向链接时被认为尚未完成。
传递给 Context 接口或其子接口之一中任何方法的 Name 参数不会被服务提供程序修改。服务提供程序可以在执行操作期间保留一个对它的引用,其中包括方法结果的所有枚举和生成的所有反向链接的处理。调用方在这段时间内不能修改该对象。任何这类方法返回的 Name 都归调用方所有。调用方随后可修改它,而服务提供程序则不能。
JNDI 应用程序需要一种方式来传达定义访问命名服务和目录服务的环境的各种首选项和属性。例如,为了访问服务,某个上下文可能需要安全证书的规约。另一个上下文可能要求提供服务器的配置信息。这些被称为某一上下文的环境 。Context 接口提供一些检索和更新此环境的方法。
该环境在上下文方法从一个上下文到下一个上下文时从父上下文中继承。对某一上下文环境的更改不会直接影响其他上下文的环境。
当将环境属性用于有效性和/或验证有效性时,这些属性与实现有关。例如,一些与安全有关的属性被服务提供程序用于“登录”目录。此登录过程可能发生在创建 上下文时,或者发生在第一次对该上下文调用方法时。无论这在何时或是否发生,此环境属性都与实现有关。在将环境属性添加到上下文中或从上下文中移除时,验 证这些更改的有效性也都与实现有关。例如,验证某些属性可能发生在进行更改时,或者发生在对上下文执行下一个操作时,抑或根本不验证。
拥有对某一上下文的引用的任何对象都可以检查该上下文的环境。敏感信息(比如明文密码)不应该存储在该环境中,除非已知实现能保护这类信息。
要简化设置 JNDI 应用程序所需环境的任务,可以将资源文件 与应用程序组件和服务提供程序一起发布。JNDI 资源文件是使用属性文件格式的文件(参见 java.util.Properties
),包括一个键/值对列表。键是属性的名称(例如 "java.naming.factory.object"),而值是使用为该属性定义的格式的字符串。以下是 JNDI 资源文件的一个示例:
java.naming.factory.object=com.sun.jndi.ldap.AttrsToCorba:com.wiz.from.Person java.naming.factory.state=com.sun.jndi.ldap.CorbaToAttrs:com.wiz.from.Person java.naming.factory.control=com.sun.jndi.ldap.ResponseControlFactory
JNDI 类库读取资源文件,并使属性值随意可用。因此应该认为 JNDI 资源文件是“所有人可读的”,敏感信息(比如明文密码)不应该存储在那里。
有两种 JNDI 资源文件:提供程序 和应用程序 。
每个服务提供程序都有一个可选的资源,该资源列出了特定于该提供程序的属性。此资源的名称是:
[ prefix /] jndiprovider.properties
其中 prefix 是提供程序的上下文实现的包名称,其每个句点 (".") 都被转换成一个斜杠 ("/")。 例如,假设服务提供程序定义了一个带有类名称 com.sun.jndi.ldap.LdapCtx 的上下文实现。此提供程序的提供程序资源被命名为 com/sun/jndi/ldap/jndiprovider.properties 。如果该类不在一个包中,则资源的名称就是 jndiprovider.properties
。
JNDI 类库中的某些方法使用指定 JNDI 工厂列表的标准 JNDI 属性:
在确定这些属性的值时,JNDI 库将参考提供程序资源文件。这以外的属性可由服务提供程序在提供程序资源文件中设置。服务提供程序的文档应该明确声明哪些属性是被允许的;文件中的其他属性将被忽略。
在部署应用程序时,该应用程序通常将在其类路径中生成若干代码基目录和 JAR。类似地,在部署 applet 时,它将有一个指定 applet 类所处地址的代码基和档案文件。JNDI 查找(使用 ClassLoader.getResources()
)类路径中所有名为 jndi.properties 的应用程序资源文件 。此外,如果文件 java.home /lib/jndi.properties 存在并且是可读的,则 JNDI 会将其视为一个额外的应用程序资源文件。(java.home 指示由 java.home 系统属性命名的目录。)包含在这些文件中的所有属性都被放置在初始上下文环境中。然后此环境由其他上下文继承。
对于同时出现在多个应用程序资源文件中的每个属性,JNDI 使用最先找到的值,或者在少数有意义的情况下串联所有这些值(细节在下文给出)。例如,如果在三个 jndi.properties 资源文件中存在 "java.naming.factory.object" 属性,则对象工厂列表是所有三个文件中的属性值的串联。使用此方案,每个可部署组件都要负责列出它导出的工厂。JNDI 在搜索工厂类时自动收集和使用所有这些导出列表。
从 Java 2 Platform 开始可使用应用程序资源文件,java.home /lib 中的文件除外,它在较早的 Java 平台上也可以使用。
当 JNDI 构造一个初始上下文时,该上下文的环境是使用传递给构造方法的环境参数中定义的属性、系统属性、applet 参数和应用程序资源文件进行初始化的。有关细节请参见 InitialContext 。然后此初始环境由其他上下文实例继承。
如果 JNDI 类库需要确定某一属性的值,它将通过按顺序合并取自以下两个源的值来实现这一点:
对于每个同时存在于这两个源中的属性,JNDI 用以下方式确定属性的值。如果该属性是指定 JNDI 工厂列表的标准 JNDI 属性之一(如上文 所列),则这些值被串联成一个以冒号分隔的列表。对于其他属性,只使用最先找到的值。
当服务提供程序需要确定某一属性的值时,它通常将直接从环境中获取该值。服务提供程序可以定义将置于其本身提供程序资源文件中的特定于提供程序的属性。在这种情况下,它应该根据上文所述合并这些值。
这样,每个服务提供程序开发人员便可以指定与该服务提供程序一起使用的工厂列表。这可以由应用程序或 applet 的部署方指定的应用程序资源修改,而这些资源又可以由用户修改。