处理 DirContext
本部分介绍了如何处理数字DirContext,包括预处理和后处理。
自定义DirContext预处理和后处理
在某些情况下,您可能希望在搜索操作之前和之后对DirContext执行操作。用于此的接口称为DirContextProcessor。以下列表显示了DirContextProcessor接口:
public interface DirContextProcessor {
public void preProcess(DirContext ctx) throws NamingException;
public void postProcess(DirContext ctx) throws NamingException;
}
The LdapTemplate 类具有一个接受 DirContextProcessor 的 search 方法,如下所示:
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 协议使用“控件”( Controls ) 来发送和接收额外数据,以影响预定义操作的行为。为简化请求控件的实现,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。如果AbstractRequestControlDirContextProcessor子类被传入一个不是LdapContext的参数,它会抛出IllegalArgumentException。 |
分页搜索结果
一些搜索可能会返回大量的结果。当没有简单的方法可以过滤出较小的结果集时,让服务器每次调用时只返回一定数量的结果会很有用。这种被称为“分页搜索结果”。然后可以逐页显示结果,并提供到下一页和上一页的链接。没有这种功能时,客户端要么手动将搜索结果分页,要么获取全部结果并将其裁剪成合适大小的页面。前者会相当复杂,后者则会消耗不必要的内存。
一些LDAP服务器支持PagedResultsControl,它要求在指定大小的页面中返回搜索操作的结果。用户通过控制搜索调用的频率来控制页面返回的速度。然而,您必须在调用之间跟踪一个cookie。服务器使用此cookie来记录上次调用分页结果请求时的进度位置。
Spring LDAP 通过在前面和后面处理一个 LdapContext 的概念来支持分页结果,如前面的章节所述。它通过使用 PagedResultsDirContextProcessor 类来实现这一点。PagedResultsDirContextProcessor 类使用请求的页面大小创建一个 PagedResultsControl 并将其添加到 LdapContext。搜索完成后,它获取 PagedResultsResponseControl 并检索分页结果cookie,该cookie用于在连续的分页结果请求之间保持上下文。
以下示例展示了如何使用分页搜索结果功能:
PagedResultsDirContextProcessor 的分页结果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,如前例所示。 |