java ldap 分页_java LDAP分页查询 解决1000条限制

三种解决方法:第一种不好用,希望有高手回帖。第三种没测试,希望有心人帮测。

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);

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LDAP(Lightweight Directory Access Protocol)是一种轻量级目录访问协议,旨在提供对目录服务的快速访问。在Java中,可以通过使用JNDI(Java Naming and Directory Interface)API来操作LDAP。 下面是一些Java操作LDAP的常见步骤和示例代码: 1.创建连接对象 ``` Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://localhost:389"); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=example,dc=com"); env.put(Context.SECURITY_CREDENTIALS, "password"); DirContext ctx = new InitialDirContext(env); ``` 2.查询数据 ``` String base = "ou=people,dc=example,dc=com"; String filter = "(objectclass=person)"; SearchControls sc = new SearchControls(); sc.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration<SearchResult> results = ctx.search(base, filter, sc); while (results.hasMore()) { SearchResult sr = (SearchResult) results.next(); // 处理查询结果 } ``` 3.添加数据 ``` Attributes attrs = new BasicAttributes(); attrs.put("cn", "John Smith"); attrs.put("sn", "Smith"); attrs.put("givenName", "John"); attrs.put("mail", "john.smith@example.com"); attrs.put("userPassword", "password"); ctx.createSubcontext("cn=John Smith,ou=people,dc=example,dc=com", attrs); ``` 4.修改数据 ``` ModificationItem[] mods = new ModificationItem[1]; mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("mail", "new-email@example.com")); ctx.modifyAttributes("cn=John Smith,ou=people,dc=example,dc=com", mods); ``` 5.删除数据 ``` ctx.destroySubcontext("cn=John Smith,ou=people,dc=example,dc=com"); ``` 这些是Java操作LDAP的一些基本步骤和示例代码,但实际应用中还需要考虑LDAP服务器的具体配置和授权等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值