Ldap 分页问题

很多文章中都有相关分页操作,以下是我使用分页操作时出现的问题,以及如何解决。

使用VirtualListViewControl分页时,还存在点问题(就是查询第一页和第二页的时候,有几条数据是重复的,希望有高手可以指点下。)

源码在附件中有。附件中是好几种分页的实现。但都不是很完美。希望有高手分享下。

package com.zhao.edu;

import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.SortControl;

public class LdapSearch {
	
	private static final String ldapHost = "ldap://192.168.32.128:389";
	private static final String loginDN = "cn=Administrator,cn=Users,dc=zhao,dc=edu,dc=com";
	private static final String password = "zhaowg";
	
	public static void main(String[] args) throws Exception{
		InitialLdapContext ctx = LdapConnection.getLdapContext(ldapHost,loginDN,password);
		try {
			
			int pageNum = 30;
			int pageSize = 500;
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
            constraints.setCountLimit(0);
            constraints.setTimeLimit(5000);
            constraints.setDerefLinkFlag(false);
            String[] attrIDs = { "sAMAccountName" ,"distingguishedName"};
            constraints.setReturningAttributes(attrIDs);
            VirtualListViewControl vctl = new VirtualListViewControl(
                    (pageNum-1)*pageSize+1, 0, 0,pageSize-1, Control.CRITICAL);
            SortControl sctl = new SortControl(
                    new String[] { "sAMAccountName" },Control.CRITICAL);
            ctx.setRequestControls(new Control[] { sctl, vctl });
            
            String baseDN="dc=zhao,dc=edu,dc=com";
            String filter="objectClass=*";
            
            NamingEnumeration<SearchResult> results = ctx.search(
                    baseDN,filter, constraints);
                int total = 0;
                while (results != null && results.hasMore()) {
                    total++;
                    SearchResult result = results.nextElement();
                    String value = result.getName();
                    //System.out.print(total + " 节点DN: " + value);
                    Attributes attrs = result.getAttributes();
                    Attribute ocAttr= attrs.get("sAMAccountName");
                    for(int i=0;ocAttr!=null && i<ocAttr.size();i++){
                      System.out.print(" " + ocAttr.get(i) +"\r\n");
                    }
                }
                System.out.println("查询条数:" + total);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			LdapConnection.closeLdapContext(ctx);
		}
		
	}
}

 

 

package com.zhao.edu;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.ldap.InitialLdapContext;

public class LdapConnection {

	/* 服务提供者 */
	private static String CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";

	/**
	 * 获取上下文
	 * @param url
	 * @param username
	 * @param pwd
	 * @return
	 */
	public static InitialLdapContext  getLdapContext(String url, String username,
			String pwd) {

		Hashtable<String, String> env = new Hashtable<String, String>();
		env.put(Context.INITIAL_CONTEXT_FACTORY, CTX_FACTORY);
		env.put(Context.PROVIDER_URL, url);
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
		env.put(Context.SECURITY_PRINCIPAL, username);
		env.put(Context.SECURITY_CREDENTIALS, pwd);
		DirContext ctx = null;
		try {
			ctx = new InitialLdapContext(env, null);
			System.out.println("认证成功");
		} catch (NamingException e) {
			e.printStackTrace();
			System.out.println("认证失败");
		}
		return (InitialLdapContext) ctx;
	}
	
	/**
	 * 关闭上下文
	 * @param ctx
	 * @throws NamingException
	 */
	public static void closeLdapContext(DirContext ctx) throws NamingException
	{
		if(null!=ctx)
		{
			ctx.close();
			System.out.println("关闭连接"); 
		}
	}
}

 

package com.zhao.edu;

import java.io.IOException;
import javax.naming.directory.InvalidAttributeValueException;
import javax.naming.ldap.*;
import com.sun.jndi.ldap.BasicControl;
import com.sun.jndi.ldap.Ber;
import com.sun.jndi.ldap.BerEncoder;

/**
 * This class implements the LDAPv3 Request Control for virtual-list-view
 * as defined in
 * <a href="http://www.ietf.org/internet-drafts/draft-ietf-ldapext-ldapv3-vlv-09.txt">draft-ietf-ldapext-ldapv3-vlv-09.txt</a>.
 *
 * The control's value has the following ASN.1 definition:
 * <pre>
 *
 *     VirtualListViewRequest ::= SEQUENCE {
 *         beforeCount    INTEGER (0 .. maxInt),
 *         afterCount     INTEGER (0 .. maxInt),
 *         CHOICE {
 *             byoffset [0] SEQUENCE {
 *                 offset          INTEGER (0 .. maxInt),
 *                 contentCount    INTEGER (0 .. maxInt)
 *             }
 *             greaterThanOrEqual [1] AssertionValue
 *         }
 *         contextID     OCTET STRING OPTIONAL
 *     }
 *
 * </pre>
 *
 * This control is always used in conjunction with the server-side sort control
 * (<a href="http://www.ietf.org/rfc/rfc2891.txt">RFC-2891</a>).
 *
 * @see VirtualListViewResponseControl
 * @see SortControl
 * @author Vincent Ryan
 */
final public class VirtualListViewControl extends BasicControl {

    /**
     * The virtual-list-view control's assigned object identifier
     * is 2.16.840.1.113730.3.4.9.
     */
    public static final String OID = "2.16.840.1.113730.3.4.9";

    /** 
     * The number of entries before the target entry in a sublist.
     *
     * @serial
     */
    private int beforeCount;

    /** 
     * The number of entries after the target entry in a sublist.
     *
     * @serial
     */
    private int afterCount;

    /** 
     * An offset into the list.
     *
     * @serial
     */
    private int targetOffset = -1;

    /** 
     * An estimate of the number of entries in the list.
     *
     * @serial
     */
    private int listSize;

    /** 
     * Attribute value used to locate the target entry.
     * This value is compared to values of the attribute specified
     * as the primary sort key.
     *
     * Only String and byte[] values are currently supported.
     *
     * @serial
     */
    private Object targetAttrValue = null;

    /**
     * A server-generated cookie.
     *
	     * @serial
	     */
	    private byte[] cookie = null;
	
	    private static final long serialVersionUID = 7739016048653396131L;
	
	    /**
	     * Constructs a virtual-list-view control.
	     *
	     * Request a view of a portion of the list centered around a given
	     * target entry. The position of the target entry is estimated as a
	     * percentage of the list.
	     *
	     * @param targetPercentage The position of the target entry expressed as a
	     *                       percentage of the list. For example, a value of
	     *                       25 indicates that the target entry is at the
	     *                       25 percent mark in the list.
	     * @param viewSize       The number of entries to be returned in this
	     *                       view of the list.
	     * @param criticality    The control's criticality setting.
	     * @exception        IllegalArgumentException if targetPercentage is
	     *                       outside the range 0-100.
	     * @exception            IOException If a BER encoding error occurs.
	     */
	    public VirtualListViewControl(int targetPercentage, int viewSize,
	    boolean criticality) throws IOException {
	
	    super(OID, criticality, null);
	
	        if ((targetPercentage > 100) ||
	        (targetPercentage < 0) ||
	        (viewSize < 0)) {
	            throw new IllegalArgumentException();
	        }
	
	    targetOffset = targetPercentage;
	    listSize = 100;
	
	    // viewSize includes the target entry
	    if (viewSize > 0) {
	        viewSize -= 1;
	    }
	    beforeCount = afterCount = viewSize / 2;
	
	    // adjust afterCount when viewSize is odd
	    if (viewSize != ((viewSize / 2) * 2)) {
	        afterCount++;
	    }
	    super.value = setEncodedValue();
	    }
	
	    /**
	     * Constructs a virtual-list-view control.
	     *
	     * Request a view of a portion of the list with the specified number of
	     * entries before and after a given target entry. The target entry is
	     * identified by means of an offset into the list.
	     *
	     * @param targetOffset The position of the target entry as an offset
	     *                     into the list.
	     * @param listSize    An estimate of the number of entries in the list.
	     * @param beforeCount  The number of entries to be returned before the
	     *                     target entry.
	     * @param afterCount   The number of entries to be returned after the
	     *                     target entry.
	     * @param criticality  The control's criticality setting.
	     * @exception          IllegalArgumentException if targetOffset, listSize,
	     *                     beforeCount or afterCount are less than zero.
	     * @exception          IOException If a BER encoding error occurs.
	     */
	    public VirtualListViewControl(int targetOffset, int listSize,
	    int beforeCount, int afterCount, boolean criticality)
	    throws IOException {
	
	    super(OID, criticality, null);
	
	    if ((targetOffset <0) || (listSize <0) ||(beforeCount <0) || (afterCount <0)){
	            throw new IllegalArgumentException();
	        }
	    
	    this.targetOffset = targetOffset;
	    this.listSize = listSize;
	    this.beforeCount = beforeCount;
	    this.afterCount = afterCount;
	    super.value = setEncodedValue();
	    }
	
	    /**
	     * Constructs a virtual-list-view critical control.
	     *
	     * Request a view of a portion of the list centered around a given
	     * target entry. The target entry is the first entry that is greater
	     * than or equal to the specified attribute value. The value's 
	     * attribute ID is the primary sort key specified in the server-side
	     * sort control.
	     *
	     * @param targetAttrValue  An attribute value used to locate the target
	     *                         entry. Its attribute ID is that of the primary
	     *                         sort key specified in the server-side sort
	     *                         control.
	     * @param viewSize         The number of entries to be returned in this
	     *                         view of the list.
	     * @param criticality      The control's criticality setting.
	     * @exception          InvalidAttributeValueException if
	     *                         targetAttrValue is neither a String nor a byte[].
	     * @exception              IOException If a BER encoding error occurs.
	     */
	    public VirtualListViewControl(Object targetAttrValue, int viewSize,
	    boolean criticality)
	    throws InvalidAttributeValueException, IOException {
	
	    super(OID, criticality, null);
	
	    if ((targetAttrValue == null) ||
	        (! ((targetAttrValue instanceof String) ||
	            (targetAttrValue instanceof byte[])))) {
	        throw new InvalidAttributeValueException();
	    }
	    this.targetAttrValue = targetAttrValue;
	
	    if (viewSize < 0) {
	        throw new IllegalArgumentException();
	    }
	
	        // viewSize includes the target entry
	        if (viewSize > 0) {
	            viewSize -= 1;
	        }
	    beforeCount = afterCount = viewSize / 2;
	
	    // adjust afterCount when viewSize is odd
	    if (viewSize != ((viewSize / 2) * 2)) {
	        afterCount++;
	    }
	    super.value = setEncodedValue();
	    }
	
	    /**
	     * Constructs a virtual-list-view control.
	     *
	     * Request a view of a portion of the list with the specified number of
	     * entries before and after a given target entry. The target entry is
	     * the first entry that is greater than or equal to the specified
	     * attribute value. The value's attribute ID is the primary sort key
	     * specified in the server-side sort control.
	     *
	     * @param targetAttrValue An attribute value used to locate the target
	     *                        entry. Its attribute ID is that of the primary
	     *                        sort key specified in the server-side sort
	     *                        control.
	     * @param beforeCount     The number of entries to be returned before the
	     *                        target entry.
	     * @param afterCount      The number of entries to be returned after the
	     *                        target entry.
	     * @param criticality     The control's criticality setting.
	     * @exception         InvalidAttributeValueException if
	     *                        targetAttrValue is neither a String nor a byte[].
	     * @exception             IllegalArgumentException if beforeCount or
	     *                        afterCount are less than zero.
	     * @exception             IOException If a BER encoding error occurs.
	     */
	    public VirtualListViewControl(Object targetAttrValue, int beforeCount,
	    int afterCount, boolean criticality)
	    throws InvalidAttributeValueException, IOException {
	
	    super(OID, criticality, null);
	
	    if ((targetAttrValue == null) ||
	        (! ((targetAttrValue instanceof String) ||
	            (targetAttrValue instanceof byte[])))) {
	        throw new InvalidAttributeValueException();
	    }
	
	    if ((beforeCount <0) || (afterCount <0)) {
	        throw new IllegalArgumentException();
	    }
	
	    this.targetAttrValue = targetAttrValue;
	    this.beforeCount = beforeCount;
	    this.afterCount = afterCount;
	    super.value = setEncodedValue();
	    }
	
	    /**
	     * Sets a server-generated cookie in the virtual-list-view request.
	     *
	     * @param contextID A server-generated cookie.
	     * @exception IOException If a BER encoding error occurs.
	     */
	    public void setContextID(byte[] contextID) throws IOException {
	    if (this.cookie != contextID) {
	        this.cookie = contextID;
	        super.value = setEncodedValue(); // re-encode
	    } else {
	        this.cookie = contextID;
	    }
	    }
	
	    /*
	     * Sets the ASN.1 BER encoded value of the virtual-list-view control.
	     * The result is the raw BER bytes including the tag and length of
	     * the control's value. It does not include the controls OID or criticality.
	     *
	     * @return A possibly null byte array representing the ASN.1 BER encoded
	     *         value of the LDAP sort control.
	     * @exception IOException If a BER encoding error occurs.
	     */
	    private byte[] setEncodedValue() throws IOException {
	
	    // build the ASN.1 encoding
	    BerEncoder ber = new BerEncoder(64);
	
	    ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
	
	        ber.encodeInt(beforeCount);
	        ber.encodeInt(afterCount);
	
	        if (targetOffset >= 0) {
	        ber.beginSeq(Ber.ASN_CONTEXT | Ber.ASN_CONSTRUCTOR | 0);
	            ber.encodeInt(targetOffset);
	            ber.encodeInt(listSize);
	        ber.endSeq();
	
	        } else {
	        if (targetAttrValue instanceof String) {
	            ber.encodeString((String)targetAttrValue,
	                     (Ber.ASN_CONTEXT | 1), true);
	        } else { // byte[]
	            ber.encodeOctetString((byte[])targetAttrValue,
	                      (Ber.ASN_CONTEXT | 1));
	        }
	        }
	        if (cookie != null) {
	        ber.encodeOctetString(cookie, Ber.ASN_OCTET_STR);
	        }
	    ber.endSeq();
	
	    return ber.getTrimmedBuf();
	    }
	}

 

 

 

1、搜索结果数据量大于10W或者50W以后,使用VirtualListViewControl.java,会出现异常:

javax.naming.OperationNotSupportedException: [LDAP: error code 12 - 00002040: SvcErr: DSID-031401E7, problem 5010 (UNAVAIL_EXTENSION), data 0

]; remaining name ''

 

解决方案: 设置AD域服务器参数:MaxTempTableSize,默认值为10000。若搜寻结果大于10W,建议设置为15W;若搜索结果大于50w,建议设置100W;若搜索结果大于100W,建议设置200W。(但不知道是否对Ldap服务器其他性能造成影响)

 

2、搜索结果数据量大于10W以上以后,使用PagedResultsControl,出现问题:PageSize设置小于1000.

pageSize设置为1000时,一直在循环获取数据,不会出现异常。若小于1000,则会出现问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值