我设法让分页像这里所描述的那样工作。问题是我需要公开一个如下所示的 API:
getUsers(pageSize, pageNumber)
,这与 JNDI/LDAP 进行分页的方式(每次传递给搜索方法时都会传递一个 cookie)不太相符。代码如下所示:
private NamingEnumeration ldapPagedSearch(String filter, int pageSize, int pageNumber){
InitialLdapContext ctx = getInitialContext();
//TODO: get the id also, need to spec it in UI
// Create the search controls
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
//keep a session
byte[] cookie = null;
//Request the paged results control
Control[] ctls = new Control[]{new PagedResultsControl(pageSize, true)};
ctx.setRequestControls(ctls);
//Specify the search scope
NamingEnumeration results = null;
int currentPage = 1;
do {
results = ctx.search(getConfiguration().get(BASEDN_KEY), filter, searchCtls);
//we got to the right page, return this page
if(currentPage == pageNumber) {
return results;
}
// loop through this page, because we cannot get a proper cookie otherwise
// WARN: this could be a problem of performance
while (results.hasMore()) results.next();
// examine the paged results control response
Control[] controls = ctx.getResponseControls();
if (controls != null) {
for (Control control : controls) {
if (control instanceof PagedResultsResponseControl) {
cookie = ((PagedResultsResponseControl) control).getCookie();
}
}
}
// pass the cookie back to the server for the next page
ctx.setRequestControls(new Control[]{new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
//increment page
currentPage++;
} while (cookie != null);
ctx.close();
//if we get here, means it is an empty set(consumed by the inner loop)
return results;
}
看来我需要遍历所有页面才能获得所需的页面。此外,我需要遍历页面上的所有条目,才能获取下一页。
有更好的方法吗?我担心性能问题。
有一种叫做“虚拟列表视图”的控件。它由几个 LDAP 服务器支持。不确定该实现是否仍在 JNDI 中。如果没有,您可以考虑自己实现。你必须将它与服务器端排序一起使用。
另请参阅 https://datatracker.ietf.org/doc/html/draft-ietf-ldapext-ldapv3-vlv-04 和 http://www.cs.rit.edu/usr/local/pub/jeh/rit/java/lib/doc/ldapcontrols/com/sun/jndi/ldap/ctl/VirtualListViewControl.html
你是对的。 API 不会凝固。您需要重新设计您应该提供的 API。