处理 DirContext
本节介绍如何处理 DirContext
,包括预处理和后处理。
自定义 DirContext
预处理和后处理
在某些情况下,您可能希望在搜索操作之前和之后对 DirContext
执行操作。用于此的接口称为 DirContextProcessor
。以下清单显示了 DirContextProcessor
接口
public interface DirContextProcessor {
public void preProcess(DirContext ctx) throws NamingException;
public void postProcess(DirContext ctx) throws NamingException;
}
LdapTemplate
类有一个搜索方法,它接受一个 DirContextProcessor
,如下所示
public void search(SearchExecutor se, NameClassPairCallbackHandler handler,
DirContextProcessor processor) throws DataAccessException;
在搜索操作之前,将调用给定 DirContextProcessor
实例上的 preProcess
方法。搜索运行完毕并处理完结果 NamingEnumeration
后,将调用 postProcess
方法。这使您能够对用于搜索的 DirContext
执行操作,并在执行搜索后检查 DirContext
。这非常有用(例如,在处理请求和响应控制时)。
如果您不需要自定义的 SearchExecutor
,也可以使用以下便捷方法
public void search(Name base, String filter,
SearchControls controls, NameClassPairCallbackHandler handler, DirContextProcessor processor)
public void search(String base, String filter,
SearchControls controls, NameClassPairCallbackHandler handler, DirContextProcessor processor)
public void search(Name base, String filter,
SearchControls controls, AttributesMapper mapper, DirContextProcessor processor)
public void search(String base, String filter,
SearchControls controls, AttributesMapper mapper, DirContextProcessor processor)
public void search(Name base, String filter,
SearchControls controls, ContextMapper mapper, DirContextProcessor processor)
public void search(String base, String filter,
SearchControls controls, ContextMapper mapper, DirContextProcessor processor)
实现请求控制 DirContextProcessor
LDAPv3 协议使用“控制”来发送和接收附加数据,以影响预定义操作的行为。为了简化请求控制 DirContextProcessor
的实现,Spring LDAP 提供了 AbstractRequestControlDirContextProcessor
基类。此类处理从 LdapContext
中检索当前请求控制,调用模板方法来创建请求控制,并将其添加到 LdapContext
中。您在子类中需要做的就是实现名为 createRequestControl
的模板方法和 postProcess
方法,以执行搜索后需要执行的操作。以下清单显示了相关的签名
public abstract class AbstractRequestControlDirContextProcessor implements
DirContextProcessor {
public void preProcess(DirContext ctx) throws NamingException {
...
}
public abstract Control createRequestControl();
}
典型的 DirContextProcessor
与以下示例类似
DirContextProcessor
实现public class MyCoolRequestControl extends AbstractRequestControlDirContextProcessor {
private static final boolean CRITICAL_CONTROL = true;
private MyCoolCookie cookie;
...
public MyCoolCookie getCookie() {
return cookie;
}
public Control createRequestControl() {
return new SomeCoolControl(cookie.getCookie(), CRITICAL_CONTROL);
}
public void postProcess(DirContext ctx) throws NamingException {
LdapContext ldapContext = (LdapContext) ctx;
Control[] responseControls = ldapContext.getResponseControls();
for (int i = 0; i < responseControls.length; i++) {
if (responseControls[i] instanceof SomeCoolResponseControl) {
SomeCoolResponseControl control = (SomeCoolResponseControl) responseControls[i];
this.cookie = new MyCoolCookie(control.getCookie());
}
}
}
}
使用控制时,请确保使用 LdapContextSource 。Control 接口是特定于 LDAPv3 的,要求使用 LdapContext 而不是 DirContext 。如果使用不是 LdapContext 的参数调用 AbstractRequestControlDirContextProcessor 子类,它将抛出 IllegalArgumentException 。
|
分页搜索结果
某些搜索可能会返回大量结果。当没有简单的方法可以过滤掉较小数量的结果时,让服务器每次调用时只返回一定数量的结果会很方便。这被称为“分页搜索结果”。然后可以显示结果的每个“页面”,并提供指向下一页和上一页的链接。如果没有此功能,客户端必须手动将搜索结果限制为页面,或者检索整个结果,然后将其切分成合适大小的页面。前者会比较复杂,而后者会消耗不必要的内存。
一些 LDAP 服务器支持 PagedResultsControl
,它请求 LDAP 服务器以指定大小的页面返回搜索操作的结果。用户通过控制搜索调用的速率来控制页面返回的速率。但是,您必须在调用之间跟踪 cookie。服务器使用此 cookie 来跟踪上次调用带分页结果请求时停止的位置。
Spring LDAP 通过使用前面章节中讨论的 `LdapContext` 的预处理和后处理概念来支持分页结果。它使用 `PagedResultsDirContextProcessor` 类来实现。`PagedResultsDirContextProcessor` 类创建一个带有请求页面大小的 `PagedResultsControl` 并将其添加到 `LdapContext` 中。搜索完成后,它获取 `PagedResultsResponseControl` 并检索分页结果 cookie,该 cookie 用于在连续的分页结果请求之间保持上下文。
以下示例展示了如何使用分页搜索结果功能。
public List<String> getAllPersonNames() {
final SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
final PagedResultsDirContextProcessor processor =
new PagedResultsDirContextProcessor(PAGE_SIZE);
return SingleContextSource.doWithSingleContext(
contextSource, new LdapOperationsCallback<List<String>>() {
@Override
public List<String> doWithLdapOperations(LdapOperations operations) {
List<String> result = new LinkedList<String>();
do {
List<String> oneResult = operations.search(
"ou=People",
"(&(objectclass=person))",
searchControls,
CN_ATTRIBUTES_MAPPER,
processor);
result.addAll(oneResult);
} while(processor.hasMore());
return result;
}
});
}
为了使分页结果 cookie 保持有效,您必须在每次分页结果调用中使用相同的底层连接。您可以通过使用 `SingleContextSource` 来实现,如前面的示例所示。 |