JNDI 命名和目录操作

2024-05-07 08:58
文章标签 操作 命名 目录 jndi

本文主要是介绍JNDI 命名和目录操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Naming and Directory Operations
原文地址: https://docs.oracle.com/javase/tutorial/jndi/TOC.html
你可以使用JNDI进行命名操作,包括读和更新操作命名空间。在本文中描述了以下操作:

  • 查找对象
  • 列出Context的内容
  • 添加,覆盖,去除绑定
  • 重命名对象
  • 创建和销毁subcontext

配置

在进行任何操作的命名或目录服务之前,您需要先获取inital Context,即开始进入命名空间的起始点。这是因为所有的命名和目录服务的方法都是在某些Context中进行的。要获得inital Context,您必须遵循以下步骤。

  • 选择要访问的相应服务的服务提供程序
  • 指定inital Context需要的配置。
  • 调用InitialContext构造函数

第一步:选择inital Context的服务供应商

您可以通过指定一组 environment properties (Hashtable类型)集合为服务提供商创建inital Context,或者向inital Context添加服务提供程序类的名称
.这个链接提供environment properties 详细的使用教程.https://docs.oracle.com/javase/jndi/tutorial/beyond/env/index.html
如果您使用的是包含在JDK的LDAP服务提供商,那么你的代码如下所示:

Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");

在JDK中指定文件系统服务提供商,那么你的代码如下所示:

Hashtable<String, Object> env = new Hashtable>String, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");

您还可以使用系统属性指定服务提供给程序使用:
https://docs.oracle.com/javase/jndi/tutorial/beyond/index.html

第二步:提供inital Context所需要的信息

不同目录的客户端可能需要不同的信息来联系目录。例如,您可能需要指明那个正在运行的服务器,以及需要什么样的信息来识别用户到该目录。这样的信息通过 environment properties传递给服务提供商. JNDI指定一些通用的 environment properties让服务提供商使用.您的服务提供程序文档将提供有关这些属性的详细信息。
LDAP提供程序要求程序指定LDAP服务器的位置,以及用户身份信息。要提供此信息,您可以编写如下代码:

env.put(Context.PROVIDER_URL, "ldap://ldap.wiz.com:389");
env.put(Context.SECURITY_PRINCIPAL, "joeuser");
env.put(Context.SECURITY_CREDENTIALS, "joepassword");

下面示例使用的LDAP服务提供者在JDK。这个例子假设服务器已经启动并使用了本地机器上的端口389与用户名字”o=JNDITutorial”.这是更新目录不需要认证。它们包括下列代码以建立环境

env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

如果您正在使用一个设置不同的目录,那么您就需要相应地设置这些环境属性。你将需要更换机器名”localhost”,您可以运行这些示例在任何非公共目录服务器或您自己的服务器上。你将需要更换机器名”localhost”和用户名o=JNDITutorial。

第三步:创建inital Context

您现在已经准备好创建inital Context。这样做,将先前创建的环境属性提供给InitialContext构造函数:

Context ctx = new InitialContext(env);

现在,您有一个Context 对象的引用,您可以开始访问命名服务。
执行目录操作,你需要使用一个InitialDirContext。要做到这一点,需使用它的构造函数:

DirContext ctx = new InitialDirContext(env);

这个语句返回一个可执行目录操作的DirContext引用对象。

命名异常

当需要的请求操作无法执行时,很多在JNDI包中的方法都有抛出NamingException。通常,你会看到一个try/catch代码块,或者抛出一个NamingException:

try {Context ctx = new InitialContext();Object obj = ctx.lookup("somename");
} catch (NamingException e) {// Handle the errorSystem.err.println(e);
}

异常类的层次结构

JNDI具有丰富的异常层次结构,所有异常都有一个共同的基类:NamingException .
下面是一个使用子类AuthenticationException的例子:

try {Context ctx = new InitialContext();Object obj = ctx.lookup("somename");
} catch (AuthenticationException e) {// attempt to reacquire the authentication information...
} catch (NamingException e) {// Handle the errorSystem.err.println(e);
}

枚举

例如Context.list() 和DirContext.search()都会返回一个NamingEnumeration.在这种情况下,如果发生了一个错误,不返回任何结果,这时NamingException 或其相应的子类将被抛出.
如果出现错误,但也有一些结果会被返回,返回一个NamingEnumeration 以便你能得到这些结果。当所有的结果都用完后,调用NamingEnumeration.hasMore()会造成NamingException (或它的一个子类)被抛出。在这点上,枚举无效,并且没有其他方法能被调用。
例如,如果你执行一个search()并指定一个数(N)限制返回多少个结果集,那么search()将返回一个包含最多N结果的结果集。如果结果数超过N,然后NamingEnumeration.hasMore()为n + 1次调用时,会抛出一个SizeLimitExceededException 。
所有的异常说明可以在这里找到:
https://docs.oracle.com/javase/8/docs/api/javax/naming/package-summary.html

查找对象

通过您要检索的对象的名称,使用 Context.lookup()查找命名服务中的对象。假设有一个对象命名服务中的名称:cn=Rosanna Lee,ou=People。要检索该对象,您将写

Object obj = ctx.lookup("cn=Rosanna Lee,ou=People");

lookup()返回的目标类型取决于底层的命名系统和对象本身相关的数据。一个命名系统可以包含许多不同类型的对象,并且在系统的不同部分中查找对象可能会产生不同类型的对象。在上面的例子中, “cn=Rosanna Lee,ou=People”恰好是绑定到Context的对象((javax.naming.ldap.LdapContext)。你可以用lookup()找到目标类:

例如,下面的代码查找对象 “cn=Rosanna Lee,ou=People”,并转换为LdapContext。

import javax.naming.ldap.LdapContext;
...
LdapContext ctx = (LdapContext) ctx.lookup("cn=Rosanna Lee,ou=People");

完整的示例文件在lookup.java:
https://docs.oracle.com/javase/tutorial/jndi/ops/examples/Lookup.java
这里写图片描述

这里有2个新的静态方法可查找一个名字在Java SE 6中:
InitialContext.doLookup(Name name)
InitialContext.doLookup(String name)
这些方法提供了一个寻找无需实例化的InitialContext的快捷方式

列出Context的内容

如果不使用Context.lookup()一次得到一个单一的对象,你可以通过使用一个单一的操作列出Context的内容。有两种方法用于列出Context:一个是返回绑定的方法,一个返回name-to-object 类。

  • Context.List()
    返回一个NameClassPair枚举,每个NameClassPair包含对象名和类名,下面的代码片段列出了”ou=People”目录的内容(即在”ou=People”目录中找到的相应的文件和目录)。
NamingEnumeration list = ctx.list("ou=People");while (list.hasMore()) {NameClassPair nc = (NameClassPair)list.next();System.out.println(nc);
}

运行这个例子产生以下输出:

# java List
cn=Jon Ruiz: javax.naming.directory.DirContext
cn=Scott Seligman: javax.naming.directory.DirContext
cn=Samuel Clemens: javax.naming.directory.DirContext
cn=Rosanna Lee: javax.naming.directory.DirContext
cn=Maxine Erlund: javax.naming.directory.DirContext
cn=Niels Bohr: javax.naming.directory.DirContext
cn=Uri Geller: javax.naming.directory.DirContext
cn=Colleen Sullivan: javax.naming.directory.DirContext
cn=Vinnie Ryan: javax.naming.directory.DirContext
cn=Rod Serling: javax.naming.directory.DirContext
cn=Jonathan Wood: javax.naming.directory.DirContext
cn=Aravindan Ranganathan: javax.naming.directory.DirContext
cn=Ian Anderson: javax.naming.directory.DirContext
cn=Lao Tzu: javax.naming.directory.DirContext
cn=Don Knuth: javax.naming.directory.DirContext
cn=Roger Waters: javax.naming.directory.DirContext
cn=Ben Dubin: javax.naming.directory.DirContext
cn=Spuds Mackenzie: javax.naming.directory.DirContext
cn=John Fowler: javax.naming.directory.DirContext
cn=Londo Mollari: javax.naming.directory.DirContext
cn=Ted Geisel: javax.naming.directory.DirContext
  • Context.listBindings()
    返回一个Binding枚举,Binding是一个NameClassPair的子类.Binding包含对象的名称和类名称,但也包含对象本身。下面的代码列举”ou=People”的Context,打印出每个绑定的名称和对象。
NamingEnumeration bindings = ctx.listBindings("ou=People");while (bindings.hasMore()) {Binding bd = (Binding)bindings.next();System.out.println(bd.getName() + ": " + bd.getObject());
}

运行这个例子产生以下输出:

# java ListBindings
cn=Jon Ruiz: com.sun.jndi.ldap.LdapCtx@1d4c61c
cn=Scott Seligman: com.sun.jndi.ldap.LdapCtx@1a626f
cn=Samuel Clemens: com.sun.jndi.ldap.LdapCtx@34a1fc
cn=Rosanna Lee: com.sun.jndi.ldap.LdapCtx@176c74b
cn=Maxine Erlund: com.sun.jndi.ldap.LdapCtx@11b9fb1
cn=Niels Bohr: com.sun.jndi.ldap.LdapCtx@913fe2
cn=Uri Geller: com.sun.jndi.ldap.LdapCtx@12558d6
cn=Colleen Sullivan: com.sun.jndi.ldap.LdapCtx@eb7859
cn=Vinnie Ryan: com.sun.jndi.ldap.LdapCtx@12a54f9
cn=Rod Serling: com.sun.jndi.ldap.LdapCtx@30e280
cn=Jonathan Wood: com.sun.jndi.ldap.LdapCtx@16672d6
cn=Aravindan Ranganathan: com.sun.jndi.ldap.LdapCtx@fd54d6
cn=Ian Anderson: com.sun.jndi.ldap.LdapCtx@1415de6
cn=Lao Tzu: com.sun.jndi.ldap.LdapCtx@7bd9f2
cn=Don Knuth: com.sun.jndi.ldap.LdapCtx@121cc40
cn=Roger Waters: com.sun.jndi.ldap.LdapCtx@443226
cn=Ben Dubin: com.sun.jndi.ldap.LdapCtx@1386000
cn=Spuds Mackenzie: com.sun.jndi.ldap.LdapCtx@26d4f1
cn=John Fowler: com.sun.jndi.ldap.LdapCtx@1662dc8
cn=Londo Mollari: com.sun.jndi.ldap.LdapCtx@147c5fc
cn=Ted Geisel: com.sun.jndi.ldap.LdapCtx@3eca90

终止一个NamingEnumeration

一个NamingEnumeration可以有三种方式:自然终止,明确,或意外。

  • 当 NamingEnumeration.hasMore()返回false,枚举是完整和有效的终止。
  • 你可以明确终止枚举通过调用 NamingEnumeration.close()。这样做为底层实现提供一个提示,以释放与枚举相关联的任何资源。
  • 如果 hasMore()或next()抛出一个NamingException,然后枚举有效终止。

为什么有两个不同的列表方法?

list()用于浏览模式的应用程序,只想在一个Context中显示对象的名称。例如,一个浏览器先用Context列出名称,并等待用户选择一个或几个然后显示执行进一步操作的名称。这样的应用程序通常不需要在Context中访问所有的对象。
listbindings()用于需要对Context的全体对象执行操作的应用程序。例如,备份应用程序可能需要在文件目录中的所有对象上执行“文件统计”操作。或者打印机管理程序可能要重新启动一个项目的所有打印机。要执行这样的操作,这些应用程序需要获得在Context中的所有对象。因此,返回对象作为枚举的一部分是更加有利.
应用程序可以使用list()或更昂贵的listBindings(),应根据信息类型的需要.

添加,替换或删除绑定

Context接口包含用于Context的添加、替换和删除绑定的方法

  • 添加绑定
    Context.bind() 用于添加一个绑定到Context中,它接受被绑定的对象名称和对象作为参数.
// 创建需要绑定的对象
Fruit fruit = new Fruit("orange");// 执行绑定
ctx.bind("cn=Favorite Fruit", fruit);

此示例创建一个水果类的对象并将它绑定到”cn=Favorite Fruit”到名为ctx的Context中。如果你随后用ctx的lookup名为:”cn=Favorite Fruit”,然后你会得到fruit 对象。
如果你运行这个例子两次,然后将抛出异常:NameAlreadyBoundException。这是因为这个名字”cn=Favorite Fruit”已经被绑定了。对于尝试第二次成功,你将不得不使用rebind()。

添加或替换绑定:
rebind()用于添加或替换绑定。它接受和bind()相同的参数,但语义是这样的,如果是已经绑定,那么它将会绑定新的对象。

// Create the object to be bound
Fruit fruit = new Fruit("lemon");// Perform the bind
ctx.rebind("cn=Favorite Fruit", fruit);

当你运行这个例子,它将取代bind()例子创建的对象
这里写图片描述

移除绑定

移除绑定使用unbind().

// Remove the binding
ctx.unbind("cn=Favorite Fruit");

下面是三个完整的例子:
https://docs.oracle.com/javase/tutorial/jndi/ops/examples/Rebind.java
https://docs.oracle.com/javase/tutorial/jndi/ops/examples/Bind.java
https://docs.oracle.com/javase/tutorial/jndi/ops/examples/Unbind.java

重命名

你可以通过 Context.rename()重命名Context中的对象

// Rename to Scott S
ctx.rename("cn=Scott Seligman", "cn=Scott S");

这个例子重命名对象被绑定到”cn=Scott Seligman”到”cn=Scott S”如下:

// Rename back to Scott Seligman
ctx.rename("cn=Scott S", "cn=Scott Seligman");

创建和销毁subcontext

Context接口包含用于创建和销毁subcontext的方法,一个context必然和另一context 为同一类型.
这里介绍的例子使用一个有属性的对象和创建subcontext到目录中。你可以使用DirContext 关联属相到对象中,同时增加binding和subcontext到命名空间。例如,您可以创建一个对象,并将其绑定到名称空间,并在同一时间关联该对象的属性。这样命名等价没有属性。
createsubcontext()会创建一个新的对象,DirContext.createSubcontext()创建一个子对象,需要指定属性和context

创建一个Context

创建一个Context,你提供给createsubcontext()Context的名称。 createsubcontext()名称的情况下,你想创建及其属性。

// Create attributes to be associated with the new context
Attributes attrs = new BasicAttributes(true); // case-ignore
Attribute objclass = new BasicAttribute("objectclass");
objclass.add("top");
objclass.add("organizationalUnit");
attrs.put(objclass);// Create the context
Context result = ctx.createSubcontext("NewOu", attrs);

此示例创建一个新的语境中被称为”ou=NewOu” 有一个属性”objectclass”的两个值,”top”和 “organizationalUnit”,在CTX的Context。

# java Create
ou=Groups: javax.naming.directory.DirContext
ou=People: javax.naming.directory.DirContext
ou=NewOu: javax.naming.directory.DirContext

此示例创建一个新的背景下,被称为”NewOu”,那是一个CTX的子Context。
这里写图片描述

销毁Context

销毁Context,你提供给destroysubcontext()Context的名称来摧毁。

// Destroy the context
ctx.destroySubcontext("NewOu");

这是销毁Context的完整代码:
https://docs.oracle.com/javase/tutorial/jndi/ops/examples/Destroy.java

这篇关于JNDI 命名和目录操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/966902

相关文章

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

Python利用自带模块实现屏幕像素高效操作

《Python利用自带模块实现屏幕像素高效操作》这篇文章主要为大家详细介绍了Python如何利用自带模块实现屏幕像素高效操作,文中的示例代码讲解详,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、获取屏幕放缩比例2、获取屏幕指定坐标处像素颜色3、一个简单的使用案例4、总结1、获取屏幕放缩比例from

通过prometheus监控Tomcat运行状态的操作流程

《通过prometheus监控Tomcat运行状态的操作流程》文章介绍了如何安装和配置Tomcat,并使用Prometheus和TomcatExporter来监控Tomcat的运行状态,文章详细讲解了... 目录Tomcat安装配置以及prometheus监控Tomcat一. 安装并配置tomcat1、安装

Python中操作Redis的常用方法小结

《Python中操作Redis的常用方法小结》这篇文章主要为大家详细介绍了Python中操作Redis的常用方法,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解一下... 目录安装Redis开启、关闭Redisredis数据结构redis-cli操作安装redis-py数据库连接和释放增

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允