Java 中文官方教程 2022 版(四十七)(1)https://developer.aliyun.com/article/1488489
使用修改列表
修改对象属性的一种方法是提供修改请求的列表(ModificationItem
)。每个ModificationItem
包含一个数字常量,指示要进行的修改类型,以及描述要进行的修改的Attribute
。以下是三种修改类型:
修改按列表中出现的顺序应用。要么执行所有修改,要么一个也不执行。
以下代码创建了一个修改列表。它用值"geisel@wizards.com"替换了"mail"
属性的值,向"telephonenumber"
属性添加了一个额外的值,并删除了"jpegphoto"
属性。
// Specify the changes to make ModificationItem[] mods = new ModificationItem[3]; // Replace the "mail" attribute with a new value mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("mail", "geisel@wizards.com")); // Add an additional value to "telephonenumber" mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("telephonenumber", "+1 555 555 5555")); // Remove the "jpegphoto" attribute mods[2] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("jpegphoto"));
Windows Active Directory: Active Directory 将"telephonenumber"定义为单值属性,与RFC 2256相悖。要使此示例针对 Active Directory 正常工作,您必须使用除"telephonenumber"之外的属性,或将DirContext.ADD_ATTRIBUTE
更改为DirContext.REPLACE_ATTRIBUTE
。
创建此修改列表后,您可以将其提供给modifyAttributes()
如下所示。
// Perform the requested modifications on the named object ctx.modifyAttributes(name, mods);
使用属性
或者,您可以通过指定修改类型和要应用修改的属性来执行修改。
例如,以下行将用orig
中的属性(在name
中标识)替换为orig
中的属性:
ctx.modifyAttributes(name, DirContext.REPLACE_ATTRIBUTE, orig);
name
的任何其他属性保持不变。
modifyAttributes()
的这两种用法在示例程序
中演示。该程序通过使用修改列表修改属性,然后使用modifyAttributes()
的第二种形式来恢复原始属性。
添加、替换具有属性的绑定
讨论了命名示例如何使用bind()
,rebind()
。DirContext
接口包含这些方法的重载版本,接受属性。您可以使用这些DirContext
方法在将绑定或子上下文添加到命名空间时将属性与对象关联起来。例如,您可以创建一个Person
对象并将其绑定到命名空间,并同时关联有关该Person
对象的属性。
添加具有属性的绑定
DirContext.bind()
用于向上下文添加具有属性的绑定。它接受对象的名称、要绑定的对象和一组属性作为参数。
// Create the object to be bound Fruit fruit = new Fruit("orange"); // Create attributes to be associated with the object Attributes attrs = new BasicAttributes(true); // case-ignore Attribute objclass = new BasicAttribute("objectclass"); objclass.add("top"); objclass.add("organizationalUnit"); attrs.put(objclass); // Perform bind ctx.bind("ou=favorite, ou=Fruits", fruit, attrs);
此示例
创建一个Fruit
类的对象,并将其绑定到名称"ou=favorite"
中,相对于ctx
命名为"ou=Fruits"
的上下文。此绑定具有"objectclass"
属性。如果随后在ctx
中查找名称"ou=favorite, ou=Fruits"
,则会获取fruit
对象。然后获取"ou=favorite, ou=Fruits"
的属性,您将获得创建对象时使用的属性。以下是此示例的输出。
# java Bind orange attribute: objectclass value: top value: organizationalUnit value: javaObject value: javaNamingReference attribute: javaclassname value: Fruit attribute: javafactory value: FruitFactory attribute: javareferenceaddress value: #0#fruit#orange attribute: ou value: favorite
显示的额外属性和属性值用于存储有关对象(fruit
)的信息。这些额外属性在本教程中将更详细地讨论。
如果您运行此示例两次,则第二次尝试将失败,并显示NameAlreadyBoundException
。这是因为名称"ou=favorite"
已经绑定在"ou=Fruits"
上下文中。为了使第二次尝试成功,您需要使用rebind()
。
替换具有属性的绑定
DirContext.rebind()
用于添加或替换绑定及其属性。它接受与bind()
相同的参数。然而,rebind()
的语义要求,如果名称已经绑定,则将解除绑定,并绑定新给定的对象和属性。
// Create the object to be bound Fruit fruit = new Fruit("lemon"); // Create attributes to be associated with the object Attributes attrs = new BasicAttributes(true); // case-ignore Attribute objclass = new BasicAttribute("objectclass"); objclass.add("top"); objclass.add("organizationalUnit"); attrs.put(objclass); // Perform bind ctx.rebind("ou=favorite, ou=Fruits", fruit, attrs);
当您运行此示例
时,它将替换bind()
示例创建的绑定。
# java Rebind lemon attribute: objectclass value: top value: organizationalUnit value: javaObject value: javaNamingReference attribute: javaclassname value: Fruit attribute: javafactory value: FruitFactory attribute: javareferenceaddress value: #0#fruit#lemon attribute: ou value: favorite
搜索
目录提供的最有用的功能之一是其黄页或搜索服务。您可以组成一个由您正在寻找的条目的属性组成的查询,并将该查询提交给目录。然后目录返回满足查询条件的条目列表。例如,您可以要求目录返回所有击球平均分大于 200 的条目,或者所有代表姓氏以"Sch"开头的人的条目。
DirContext
接口提供了几种搜索目录的方法,具有逐渐增加的复杂性和功能。搜索目录的各个方面在以下部分中介绍:
- 基本搜索
- 搜索过滤器
- 搜索控件
基本搜索
原文:
docs.oracle.com/javase/tutorial/jndi/ops/basicsearch.html
最简单的搜索形式要求您指定条目必须具有的属性集,以及执行搜索的目标上下文的名称。
以下代码创建了一个属性集matchAttrs
,其中包含两个属性"sn"
和"mail"
。 它指定符合条件的条目必须具有一个姓氏("sn"
)属性,其值为"Geisel"
,以及一个任何值的"mail"
属性。 然后调用DirContext.search()
在上下文"ou=People"
中搜索具有matchAttrs
指定属性的条目。
// Specify the attributes to match // Ask for objects that has a surname ("sn") attribute with // the value "Geisel" and the "mail" attribute // ignore attribute name case Attributes matchAttrs = new BasicAttributes(true); matchAttrs.put(new BasicAttribute("sn", "Geisel")); matchAttrs.put(new BasicAttribute("mail")); // Search for objects that have those matching attributes NamingEnumeration answer = ctx.search("ou=People", matchAttrs);
你可以按照以下方式打印结果。
while (answer.hasMore()) { SearchResult sr = (SearchResult)answer.next(); System.out.println(">>>" + sr.getName()); printAttrs(sr.getAttributes()); }
printAttrs()
类似于getAttributes()
示例中打印属性集的代码。
运行这个例子
会产生以下结果。
# java SearchRetAll >>>cn=Ted Geisel attribute: sn value: Geisel attribute: objectclass value: top value: person value: organizationalPerson value: inetOrgPerson attribute: jpegphoto value: [B@1dacd78b attribute: mail value: Ted.Geisel@JNDITutorial.example.com attribute: facsimiletelephonenumber value: +1 408 555 2329 attribute: cn value: Ted Geisel attribute: telephonenumber value: +1 408 555 5252
返回选定的属性
前面的例子返回满足指定查询条件的条目关联的所有属性。 您可以通过向search()
传递要包含在结果中的属性标识符数组来选择要返回的属性。 在之前显示的创建matchAttrs
之后,您还需要创建属性标识符数组,如下所示。
// Specify the ids of the attributes to return String[] attrIDs = {"sn", "telephonenumber", "golfhandicap", "mail"}; // Search for objects that have those matching attributes NamingEnumeration answer = ctx.search("ou=People", matchAttrs, attrIDs);
这个例子
返回具有属性"sn"
、"telephonenumber"
、"golfhandicap"
和"mail"
的条目,这些条目具有一个属性"mail"
,并且具有一个值为"Geisel"
的"sn"
属性。 这个例子产生以下结果。(该条目没有"golfhandicap"
属性,因此不返回。)
# java Search >>>cn=Ted Geisel attribute: sn value: Geisel attribute: mail value: Ted.Geisel@JNDITutorial.example.com attribute: telephonenumber value: +1 408 555 5252
过滤器
除了使用一组属性指定搜索外,还可以以搜索过滤器的形式指定搜索。搜索过滤器是以逻辑表达式形式表达的搜索查询。DirContext.search()
接受的搜索过滤器语法在RFC 2254中有描述。
以下搜索过滤器指定符合条件的条目必须具有值为"Geisel"
的"sn"
属性和任何值的"mail"
属性:
(&(sn=Geisel)(mail=*))
以下代码创建一个过滤器和默认的SearchControls
,并使用它们执行搜索。该搜索等同于基本搜索示例中呈现的搜索。
// Create the default search controls SearchControls ctls = new SearchControls(); // Specify the search filter to match // Ask for objects that have the attribute "sn" == "Geisel" // and the "mail" attribute String filter = "(&(sn=Geisel)(mail=*))"; // Search for objects using the filter NamingEnumeration answer = ctx.search("ou=People", filter, ctls);
运行此示例
会产生以下结果。
# java SearchWithFilterRetAll >>>cn=Ted Geisel attribute: sn value: Geisel attribute: objectclass value: top value: person value: organizationalPerson value: inetOrgPerson attribute: jpegphoto value: [B@1dacd75e attribute: mail value: Ted.Geisel@JNDITutorial.example.com attribute: facsimiletelephonenumber value: +1 408 555 2329 attribute: cn value: Ted Geisel attribute: telephonenumber value: +1 408 555 5252
搜索过滤器语法快速概述
搜索过滤器语法基本上是前缀表示法中的逻辑表达式(即,逻辑运算符出现在其参数之前)。以下表列出了用于创建过滤器的符号。
符号 | 描述 |
& | 合取(即,与 — 列表中的所有项目必须为真) |
| | 析取(即,或 — 一个或多个备选项必须为真) |
! | 否定(即,非 — 被否定的项目必须为假) |
= | 等于(根据属性匹配规则) |
~= | 大致相等(根据属性匹配规则) |
>= | 大于(根据属性匹配规则) |
<= | 小于(根据属性匹配规则) |
=* | 存在(即,条目必须具有属性,但其值无关紧要) |
* | 通配符(表示该位置可以出现零个或多个字符);用于指定要匹配的属性值时使用 |
\ | 转义(用于在属性值中出现’*‘、’(‘或’)'时进行转义) |
每个过滤器中的项目都是使用属性标识符和属性值或表示属性值的符号组成的。例如,项目"sn=Geisel"
表示"sn"
属性必须具有属性值"Geisel"
,而项目"mail=*"
表示"mail"
属性必须存在。
每个项目必须用一组括号括起来,如"(sn=Geisel)"
。这些项目使用逻辑运算符(如"&"(合取))组合,以创建逻辑表达式,如"(& (sn=Geisel) (mail=*))"
。
每个逻辑表达式都可以进一步由其他本身是逻辑表达式的项目组成,就像"(| (& (sn=Geisel) (mail=*)) (sn=L*))"
中那样。最后一个示例请求具有"sn"
属性为"Geisel"
和"mail"
属性的条目,或者其"sn"
属性以字母"L"开头的条目。
有关语法的完整描述,请参阅RFC 2254。
返回选定属性
前面的示例返回满足指定过滤器的条目关联的所有属性。您可以通过设置搜索控件参数来选择要返回的属性。您可以创建一个要包含在结果中的属性标识符数组,并将其传递给SearchControls.setReturningAttributes()
。以下是一个示例。
// Specify the ids of the attributes to return String[] attrIDs = {"sn", "telephonenumber", "golfhandicap", "mail"}; SearchControls ctls = new SearchControls(); ctls.setReturningAttributes(attrIDs);
这个示例等同于基本搜索部分中的返回选定属性示例。运行这个示例
会产生以下结果。(该条目没有"golfhandicap"
属性,因此不会返回。)
# java SearchWithFilter >>>cn=Ted Geisel attribute: sn value: Geisel attribute: mail value: Ted.Geisel@JNDITutorial.example.com attribute: telephonenumber value: +1 408 555 5252
范围
默认的SearchControls
指定搜索在命名上下文中执行(SearchControls.ONELEVEL_SCOPE
)。这个默认设置在搜索过滤器部分的示例中使用。
除了这个默认设置外,您还可以指定搜索在整个子树或仅在命名对象中执行。
搜索子树
对整个子树进行搜索将搜索命名对象及其所有后代。要使搜索以这种方式执行,请将SearchControls.SUBTREE_SCOPE
传递给SearchControls.setSearchScope()
如下所示。
// Specify the ids of the attributes to return String[] attrIDs = {"sn", "telephonenumber", "golfhandicap", "mail"}; SearchControls ctls = new SearchControls(); ctls.setReturningAttributes(attrIDs); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); // Specify the search filter to match // Ask for objects that have the attribute "sn" == "Geisel" // and the "mail" attribute String filter = "(&(sn=Geisel)(mail=*))"; // Search the subtree for objects by using the filter NamingEnumeration answer = ctx.search("", filter, ctls);
这个示例
搜索上下文ctx
的子树,查找满足指定过滤器的条目。它在这个子树中找到了满足过滤器的条目"cn= Ted Geisel, ou=People"
。
# java SearchSubtree >>>cn=Ted Geisel, ou=People attribute: sn value: Geisel attribute: mail value: Ted.Geisel@JNDITutorial.example.com attribute: telephonenumber value: +1 408 555 5252
搜索命名对象
你也可以搜索命名对象。例如,测试命名对象是否符合搜索过滤器非常有用。要搜索命名对象,请将SearchControls.OBJECT_SCOPE
传递给setSearchScope()
。
// Specify the ids of the attributes to return String[] attrIDs = {"sn", "telephonenumber", "golfhandicap", "mail"}; SearchControls ctls = new SearchControls(); ctls.setReturningAttributes(attrIDs); ctls.setSearchScope(SearchControls.OBJECT_SCOPE); // Specify the search filter to match // Ask for objects that have the attribute "sn" == "Geisel" // and the "mail" attribute String filter = "(&(sn=Geisel)(mail=*))"; // Search the subtree for objects by using the filter NamingEnumeration answer = ctx.search("cn=Ted Geisel, ou=People", filter, ctls);
这个示例
测试对象"cn=Ted Geisel, ou=People"
是否满足给定的过滤器。
# java SearchObject >>> attribute: sn value: Geisel attribute: mail value: Ted.Geisel@JNDITutorial.example.com attribute: telephonenumber value: +1 408 555 5252
该示例找到一个答案并将其打印出来。请注意,结果的名称是空字符串。这是因为对象的名称始终相对于搜索上下文命名(在本例中为"cn=Ted Geisel, ou=People"
)。
Java 中文官方教程 2022 版(四十七)(3)https://developer.aliyun.com/article/1488501