三种解决方法:第一种不好用,希望有高手回帖。第三种没测试,希望有心人帮测。 1、 batch size Batch Size When you invoke list(), listBindings(), or any of the search() methods, the LDAP service provider interacts with the LDAP server to retrieve the results and returns them in the form of a NamingEnumeration. The LDAP s ervice provider can collect all the results before returning the NamingE numeration, or it can return each result as the caller invokes NamingEnu meration.next() or NamingEnumeration.nextElement(). You can control how the LDAP service provider behaves in this respect by using the Context.B ATCHSIZE ("java.naming.batchsize") environment property. This property c ontains the string representation of a decimal integer. The LDAP service provider uses its value to determine how many results to read from the server before unblocking--this number of results is called the batch siz e--and allowing the client program to get the results by using next() or nextElement(). When the client program exhausts the batch, the LDAP ser vice provider fetches another batch so that the client program can conti nue with the enumeration. If the batch size is zero, then the service pr ovider will block until all results have been read. If this property was not set, then the default batch size is 1. When you invoke search(), for example by using a batch size of n, the LD AP provider will block until it reads n results from the server before r eturning. So, setting the batch size to a smaller number allows the prog ram to unblock sooner. However, some overhead attaches to processing eac h batch. If you are expecting a large number of results, then you might want to use a larger batch size to lower the number of context switches between the provider and your code. On the other hand, having a large ba tch also means that you need more memory to hold the results. These are the trade-offs that you'll need to consider when choosing a batch size. Here's an example that sets the batch size to 10. // Set the batch size to 10 env.put("java.naming.batchsize", "10"); // Create the initial context DirContext ctx = new InitialDirContext(env); // Perform the list NamingEnumeration answer = ctx.list("ou=People"); Relationship to SearchControls.setCountLimit() Note that the Context.BATCHSIZE environment property does not in any way affect how many results are returned or the order in which they are ret urned. It is completely unrelated to SearchControls.setCountLimit(). 经过实验,发现这种方法好象没用,不清楚为什么,等有空的时候需要研究一下。 2、paged search A few other problems that developers come across are queries that return either a large number of results, or query that returns a multi-valued attribute that contains a large number of values. Active Directory incorporates a number of controls, that are designed to ensure optimim performance of the server and to mitigate denial of serv ice attacks. First of all paging. By default, Active Directory restricts the total nu mber of results that are returned from a LDAP Search to 1000. While this limit can be changed by modifying the LDAP Query policy, the recomended approach is to use paged results. Note that this ample, which queries f or all users that have a value for the mail attribute. uses a page size of 10, not really an optimal use of either the server or of the network, but merely just to demonstrate paging. Also, the usual security comments apply, you shouldn't hardcode credenti als in an application, authentication should either use Kerberos (JAAS & GSSAPI) or if using simple authentication, secured using SSL or TLS, an d and any sensitive information communicated between the client and the server should also take place over SSL or TLS. . /** * paged.java * 5 July 2001 * Sample JNDI application that performs a paged search. * */ import java.util.Hashtable; import java.util.Enumeration; import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.*; import com.sun.jndi.ldap.ctl.*; class paged { public static void main(String[] args) { Hashtable env = new Hashtable(); String adminName = "CN=Administrator,CN=Users,DC=antipodes,DC=com"; String adminPassword = "XXXXXXXX"; String searchBase = "DC=antipodes,DC=com"; String searchFilter = "(&(objectClass=user)(mail=*))"; env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFact ory"); //set security credentials, note using simple cleartext authentication env.put(Context.SECURITY_AUTHENTICATION,"simple"); env.put(Context.SECURITY_PRINCIPAL,adminName); env.put(Context.SECURITY_CREDENTIALS,adminPassword); //connect to my domain controller env.put(Context.PROVIDER_URL, "ldap://mydc.antipodes.com:389"); try { // Create the initial directory context LdapContext ctx = new InitialLdapContext(env,null); // Create the search controls SearchControls searchCtls = new SearchControls(); //Specify the attributes to return String returnedAtts[]={"sn","givenName","mail"}; searchCtls.setReturningAttributes(returnedAtts); //Specify the search scope searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); //Set the page size and initialize the cookie that we pass back in su bsequent pages int pageSize = 10; byte[] cookie = null; //Request the paged results control Control[] ctls = new Control[]{new PagedResultsControl(pageSize)}; ctx.setRequestControls(ctls); //initialize counter to total the results int totalResults = 0; // Search for objects using the filter do { NamingEnumeration results = ctx.search(searchBase, searchFilter, sea rchCtls); // loop through the results in each page while (results != null && results.hasMoreElements()) { SearchResult sr = (SearchResult)results.next(); //print out the name System.out.println("name: " + sr.getName()); //increment the counter totalResults++; } // examine the response controls cookie = parseControls(ctx.getResponseControls()); // pass the cookie back to the server for the next page ctx.setRequestControls(new Control[]{new PagedResultsControl(pageSize , cookie, Control.CRITICAL) }); } while ((cookie != null) && (cookie.length != 0)); ctx.close(); System.out.println("Total entries: " + totalResults); } catch (NamingException e) { System.err.println("Paged Search failed." + e); } catch (java.io.IOException e) { System.err.println("Paged Search failed." + e); } } static byte[] parseControls(Control[] controls) throws NamingException { byte[] cookie = null; if (controls != null) { for (int i = 0; i < controls.length; i++) { if (controls[i] instanceof PagedResultsResponseControl) { PagedResultsResponseControl prrc = (PagedResultsResponseControl)con trols[i]; cookie = prrc.getCookie(); System.out.println(">>Next Page \n"); } } } return (cookie == null) ? new byte[0] : cookie; } } 经测试,这种方法可以解决问题 3、range search Note that if we had requested a multi-valued attribute instead of the su rname (sn), firstname (givenName) and e-mail (mail) attributes, and if t hat multi-valued had more than 1000 values, then only the first 1000 val ues would have been returned, irrespective of whether paged results had ben used. Range retrieval is more evident when retrieving the list of members from a group. The list of members in a group is contained in the member attr ibute. If there are more than 1000 values in the member attribute, then you must use range retrieval to return all the members. Information on range retrieval can be found at http://msdn.microsoft.com /library/default.asp?url=/library/en-us/adsi/adsi/attribute_range_retrie val.asp The following JNDI sample illustrates the retrieval of members from a gr oup, using range retrieval. In this case querying for the list of member s of a group called "All Research" in the Active Directory. /** * range.java * December 2004 * Sample JNDI application to demonstrate range retrieval * */ import java.util.Hashtable; import javax.naming.*; import javax.naming.ldap.*; import javax.naming.directory.*; import com.sun.jndi.ldap.ctl.*; //if we were going to do this properly, should check that the server sup ports //the range retrieval control 1.2.840.113556.1.4.802 ! public class range { public static void main (String[] args) { Hashtable env = new Hashtable(); String adminName = "CN=Administrator,CN=Users,DC=ANTIPODES,DC=COM"; String adminPassword = "XXXXXX"; env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFact ory"); //set security credentials, note using simple cleartext authentication env.put(Context.SECURITY_AUTHENTICATION,"simple"); env.put(Context.SECURITY_PRINCIPAL,adminName); env.put(Context.SECURITY_CREDENTIALS,adminPassword); //connect to my domain controller env.put(Context.PROVIDER_URL,"ldap://mydc.antipodes.com:389"); try { // Create the initial directory context LdapContext ctx = new InitialLdapContext(env,null); // Create the search controls SearchControls searchCtls = new SearchControls(); //Specify the search scope searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); //specify the LDAP search filter String searchFilter = "(&(objectClass=group)(CN=All Research))"; //Specify the Base for the search String searchBase = "DC=antipodes,DC=com"; //initialize counter to total the group members and range values int totalResults = 0; int Start = 0; int Step = 10; int Finish = 9; boolean Finished = false; String Range; //loop through the query until we have all the results while (!Finished) { //Specify the attributes to return Range = Start + "-" + Finish; String returnedAtts[]={"member;Range=" + Range}; searchCtls.setReturningAttributes(returnedAtts); //Search for objects using the filter NamingEnumeration answer = ctx.search(searchBase, searchFilter, sear chCtls); //Loop through the search results while (answer.hasMoreElements()) { SearchResult sr = (SearchResult)answer.next(); System.out.println(">>>" + sr.getName()); //Print out the members Attributes attrs = sr.getAttributes(); if (attrs != null) { try { for (NamingEnumeration ae = attrs.getAll();ae.hasMore();) { Attribute attr = (Attribute)ae.next(); //check if we are finished if (attr.getID().endsWith("*")) { Finished=true; } System.out.println("Attribute: " + attr.getID()); for (NamingEnumeration e = attr.getAll();e.hasMore();totalResult s++) { System.out.println(" " + totalResults + ". " + e.next()); } } } catch (NamingException e) { System.err.println("Problem printing attributes: " + e); } Start = Start + Step; Finish = Finish + Step; } } } System.out.println("Total members: " + totalResults); ctx.close(); } catch (NamingException e) { System.err.println("Problem searching directory: " + e); } } }
java LDAP分页查询 解决1000条限制
最新推荐文章于 2024-07-16 05:11:18 发布