有人在這裡討論一下,javax.naming.ldap.PagedResultsControl ,ldap分頁的問題嗎?
sun的jndi中提供的分頁功能javax.naming.ldap.PagedResultsControl ,好像用起來不太爽,不知道大家怎麼處理的,
比如,我是在b/s模式中進行分頁,可能是我理解的錯誤,這個介面的分頁好像是從一個上一個查詢中返回的結果中取得cookie才能翻到下一頁,但是在b/s模式中,從第一頁直接翻到第N頁,哪不是要先得到N-1個cookie??這樣每次從頭翻到尾還有什麼意義呢? 哪位仁兄,達人,可以切磋一下?
[ 本帖最後由 wangbaohua 於 2007-1-23 19:01 編輯 ]
《解決方案》
自己先頂一個,目前好像目錄的分頁功能並不是所有的伺服器都技持,
大家知道技持分頁功能的目錄服務有哪些??
雖然同為sun自己的東西,netscape.ldap.controls.LDAPVirtualListControl,跟他自己標準的
javax.naming.ldap.PagedResultsControl 用法好像就完全不一樣,前者只要用
LDAPVirtualListControl(int startIndex, int beforeCount, int afterCount, int contentCount)
就可以了,
《解決方案》
關注!!
《解決方案》
http://www3.ietf.org/proceedings/03mar/I-D/draft-ietf-ldapext-ldapv3-vlv-09.txt,
LDAP Extensions for Scrolling View Browsing of Search Results
http://www.ietf.org/rfc/rfc2696.txt,
LDAP Control Extension for Simple Paged Results Manipulation
顯然這兩個東西是不一樣的,前一個簡稱vlv,這樣來看sun的標準介面對於開發來說提供的支持還不是很全面,我想各個目錄服務自己提供的sdk應該都有類似這樣功能的實現吧! 比較了一下,實現了vlv的介面可能在功能上更好用, 但是sun提供的提介面從方向上來說,更可能是一種標準,只是不知道他們什麼時候提供vlv功能。
《解決方案》
下載了所有的jndi的擴展包下來,一個一個看過,終於發現sun的vlv介面在ldapbp-1_0.zip(LDAP Booster Pack 1.0 Release)中
《解決方案》
做一個分頁的例子,運行成功,但是速度是非常的慢,我在50000條數據中做分頁,每頁大小才20,
但是每查詢一次好像要48875ms,基本上屬於不可用的狀態。
伺服器環境是sun one directory server 5.2 ,win2003,
暫時不知道是什麼原因,導致慢,因為就算我把50000條記錄全部輸出花的時間也只有這個時間的零頭。
有人懂這個原理的么??
import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.*;
import java.io.IOException;
import java.util.*;
import com.sun.jndi.ldap.ctl.*;
public class PageMain {
public static void main(String[] args) {
Hashtable m_env = new Hashtable(5, 0.75f);
LdapContext m_Ctx;
m_env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
m_env.put("java.naming.ldap.version", "3");
m_env.put(Context.PROVIDER_URL, "ldap://192.168.1.153:12345");
m_env.put(Context.SECURITY_AUTHENTICATION, "simple");
m_env.put(Context.SECURITY_PRINCIPAL, "cn=Directory Manager");
m_env.put(Context.SECURITY_CREDENTIALS,"12345678");
try{
m_Ctx = new InitialLdapContext(m_env, null);
boolean b = true;
int counter = 0;
int listSize = 0;
int i = 0;
int nTargetOffset = 1;
int nPageSize = 20;
while (b) {
VirtualListViewControl vctl
= new VirtualListViewControl(nTargetOffset, 0, 0, nPageSize, Control.CRITICAL);
javax.naming.ldap.SortControl sctl
=new javax.naming.ldap.SortControl(new String[] { "cn" },Control.CRITICAL);
m_Ctx.setRequestControls(new Control[] { sctl, vctl });
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
String[] retAtt = { "cn" };
constraints.setReturningAttributes(retAtt);
String searchCondition = "(objectclass=inetOrgPerson)";
System.out.println("-----------"+i+"-----------");
i++;
NamingEnumeration results =
m_Ctx.search("dc=com", searchCondition,constraints);
System.out.println(m_Ctx);
int subcounter = 0;
if (results != null) {
System.out.println("---------println results-----------");
while (results.hasMoreElements()) {
subcounter++;
SearchResult si = (SearchResult) results.nextElement();
counter++;
System.out.println(si.getName());
}
System.out.println(searchCondition + " returned "+ subcounter);
if (subcounter == 0){
b = false;
}
} else{
System.out.println(searchCondition+ " did not match with any!!!");
}
System.out.println("------------------NEW PAGE NO. " + i);
nTargetOffset += subcounter; // nPageSize; //subcounter;
}
} catch (NamingException e) {
e.printStackTrace();
System.out.println(e);
}catch (IOException ex) {
System.out.print(ex);
}
}
}
《解決方案》
上面同樣的分頁功能在 openldap 2.2.*中,執行不能成功,
報錯:
javax.naming.OperationNotSupportedException: ; remaining name ……
我沒有看到openldap說支持vlv,是不是它就不支持。
《解決方案》
終於採用在 netscape.ldap 的sdk中提供的vlv方法分頁成功,速度還不錯,
只是留下幾個疑問,如果把jndi比作jdbc,哪么看來各個目錄對jndi的支持還不夠,
包括sun自己。如果真要做什麼開發如果不用jndi可能使程序失去復用性。
目前我在做一個目錄的應用,在選擇目錄伺服器上,和採用的開發介面上,正在猶豫中……
現在我的基本想法,就是基本netscape 和它自己的sdk來做,因為我不是做產品,
專用也就專用了,我現在想做一些基本的封裝,把邏輯層和目錄操作區分一下。
也試過spring的ldap,沒多看,基為它是基於jndi的所以還是不太放心,
另:第一次發帖,發現好像自言自語,好不凄涼……,希望對大家有些幫助
《解決方案》
回復 8樓 wangbaohua 的帖子
我也有同感,之前寫了一個spring ldap分頁的測試用例,可是怎麼都跑不起來,鬱悶。
現將代碼貼出來,請大俠指點一下:
package com.cvicse.sso.console.dao;
import javax.naming.directory.SearchControls;
import junit.framework.TestCase;
import org.springframework.ldap.CollectingNameClassPairCallbackHandler;
import org.springframework.ldap.support.control.PagedResultsCookie;
import org.springframework.ldap.support.control.PagedResultsRequestControl;
import com.cvicse.sso.console.dao.ldap.LdapTemplateExtend;
import com.cvicse.sso.console.dao.ldap.CAASUserAttributesMapper;
public class LdapTemplatePagedSearchITest extends TestCase {
private LdapTemplateExtend tested;
// LDAP contains 5 persons matching the filter. Page size is 3.
// Expects two batches of 3 and 2 persons respectively.
public void testPagedResult() {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String base = "dc=cvicse,dc=com";
String filter = "(&(objectclass=person)(cn=zhouzhou))";
CAASUserAttributesMapper mapper = new CAASUserAttributesMapper();
CollectingNameClassPairCallbackHandler handler = tested.new AttributesMapperCallbackHandler(
mapper);
PagedResultsRequestControl requestControl;
requestControl = new PagedResultsRequestControl(3);
tested.search(base, filter, searchControls, handler, requestControl);
PagedResultsCookie cookie = requestControl.getCookie();
assertNotNull("Cookie should not be null yet", cookie.getCookie());
assertEquals(3, handler.getList().size());
// Prepare for second and last search
requestControl = new PagedResultsRequestControl(3, cookie);
tested.search(base, filter, searchControls, handler, requestControl);
cookie = requestControl.getCookie();
assertNull("Cookie should be null now", cookie.getCookie());
assertEquals(5, handler.getList().size());
}
}
《解決方案》
關注中.....