这里将要介绍如何将从LDAP中查询出来的结果按照我们自己的业务需求来排序,文中所有的代码均可以单独运行成功,需要注意的地方我会特别注明。
需要引用的包:ldapjdk_4.1.jar(下载链接在文章末尾处)。
这里我首先要提前申明一些前提:
我的需求是要将每个节点下的所有子节点按照他们的某一个属性进行排序,但是又仅限于本级,不延伸至下面节点的子节点:
dc=itrus,dc=com,dc=cn
|---ou=集团总部
|---ou=公司领导
|---ou=办公室
|---ou=新闻中心
|---ou=河北分公司
|---ou=软件部
|---ou=硬件部
|---ou=测试部
这是一个简单的结构,我们要求当查询某个节点后,得到的结果是按照他们的某一个属性进行排序的,例如,这些所有的节点都有一个共同的属性:orderCode,我用它来对结果排序,我的orderCode值为:
集团总部--orderCode=100, 公司领导---orderCode=100, 办公室---orderCode=200,新闻中心---orderCode=300,
河北分公司----orderCode=200, 软件部---orderCode=100, 硬件部----orderCode=200, 测试部-----orderCode-300
下面开始正式的例子,首先我需要将下载好的JAR包Build Path到项目中,然后代码如下:
1 package com.test; 2 3 import java.util.Comparator; 4 import java.util.Map; 5 import java.util.TreeMap; 6 7 import netscape.ldap.LDAPCompareAttrNames; 8 import netscape.ldap.LDAPConnection; 9 import netscape.ldap.LDAPEntry; 10 import netscape.ldap.LDAPException; 11 import netscape.ldap.LDAPReferralException; 12 import netscape.ldap.LDAPSearchResults; 13 import netscape.ldap.util.ConnectionPool; 14 15 public class SearchPageSort { 16 private static final String HOST="localhost"; 17 private static final int PORT=389; 18 private static final int MIN_CONN_SIZE=1; 19 private static final int MAX_CONN_SIZE=5; 20 private static final String USER_ID="cn=Manager,dc=itrus,dc=com,dc=cn"; 21 private static final String PASSWORD="password"; 22 private static ConnectionPool connPool; 23 24 static{ 25 try{ 26 connPool=new ConnectionPool(MIN_CONN_SIZE,MAX_CONN_SIZE,HOST,PORT); 27 }catch(LDAPException e){ 28 e.printStackTrace(); 29 } 30 } 31 public static ConnectionPool getConnectionPool(){ 32 return SearchPageSort.connPool; 33 } 34 public static LDAPConnection getConnection(){ 35 LDAPConnection conn=SearchPageSort.getConnectionPool().getConnection(); 36 try{ 37 conn.authenticate(USER_ID, PASSWORD); 38 }catch(LDAPException e){ 39 e.printStackTrace(); 40 } 41 return conn; 42 } 43 public static void closeConnection(LDAPConnection conn){ 44 SearchPageSort.getConnectionPool().close(conn); 45 } 46 public static void main(String[] args) throws LDAPException { 47 LDAPConnection con=SearchPageSort.getConnection(); 48 String[] ATTRS={"orderCode"}; 49 LDAPSearchResults res=con.search("ou=集团总部,dc=itrus,dc=com,dc=cn", LDAPConnection.SCOPE_ONE, "orderCode=*", ATTRS, false); 50 51 LDAPCompareAttrNames compareAttrNames=new LDAPCompareAttrNames("orderCode",true); 52 res.sort(compareAttrNames); 53 Map<Integer,LDAPEntry> map=new TreeMap<Integer,LDAPEntry>(new Comparator<Integer>() { 54 public int compare(Integer obj1, Integer obj2) { 55 // 升序或降序 56 return obj1.compareTo(obj2); 57 //如果需要降序排序则用下面这句 58 // return obj2.compareTo(obj1); 59 } 60 }); 61 while(res.hasMoreElements()){ 62 try{ 63 LDAPEntry entry=res.next(); 64 map.put(Integer.parseInt(entry.getAttribute("orderCode").getStringValueArray()[0]), entry); 65 }catch(LDAPReferralException e){ 66 e.printStackTrace(); 67 continue; 68 }catch(LDAPException e){ 69 e.printStackTrace(); 70 continue; 71 } 72 } 73 for(int i:map.keySet()){ 74 System.out.print(map.get(i).getDN()+" "); 75 System.out.println(map.get(i).getAttribute("orderCode").getStringValueArray()[0]); 76 } 77 } 78 }
如果在64行处添加System.out.println(entry);这行代码,你将看到结果是按照字典顺序排的序,并没有按照数字的大小来排序。
这就是一个简单的排序例子,由于我没有在API中找到怎样对数字按照大小的顺序来排序,所以做了一个TreeMap,用orderCode值作为键,然后实现内部类对键进行排序以此来实现按照orderCode升序或者降序的排列,当然这个也是有局限性的,如果你在第49行使用了LDAPConnection.SCOPE_SUB,并且所查询的节点下面还有子节点,那么你得到的将是一个错误的结果。
--------------------------
参考资料:
http://www.docin.com/p-301603315.html?qq-pf-to=pcqq.c2c#userconsent#
如果在运行时候遇到这个错误
error result (2); historical protocol version requested, use LDAPv3 instead; Protocol error
产生这个问题的原因是因为我在客户端bind的协议是LDAPv2,而OpenLDAP服务器使用的协议是LDAPv3,所以无法访问.
解决问题的方法是:需改slapd.conf,在其中加入一句allow bind_v2,重启ldap服务即可.(不要加在最下面)
ldapjdk_4.1.jar下载链接:http://pan.baidu.com/s/1eQdzjSQ