- 浏览: 215408 次
- 性别:
- 来自: 哈尔滨
文章分类
最新评论
-
lizhenzhendebishe:
提示An error was discovered proce ...
WebService:Axis客户端调用需要身份验证的CXF服务 -
yuanliangding:
学习了。不太接触底层的东西
UNIX系统的IO模型 -
_copythat:
加油,。。。
阳光总会在风雨之后洒向苍茫 -
donlianli:
莫非去淘宝菜鸟网络了?
阳光总会在风雨之后洒向苍茫 -
菜鸟小于:
我也是哈尔滨的,在广州做了三年的开发,可是实际上我们是在维护一 ...
阳光总会在风雨之后洒向苍茫
LDAP服务器端可以支持分页查询,但是有个前提条件,需要客户端先发送按关键字排序的指令后,才能执行分页查询。排序的过程是比较耗费时间的,需要对服务器做很多优化的操作。
我的方法是在迭代结果集的时候实现分页,见代码:
package ldap.page; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.InitialLdapContext; /** * LDAP分页查询,使用时需要异步统计返回结果集的总行数 * @author sxl * */ public class LdapSearch { /** * 根据条件查找指定DN的条目下的一层所有属性 * * @param dn * 要查询的BaseDN名称 * @param filter * 要查询的过滤字符串 * @param returnedAtts * 要查找的属性 * @param start * 开始行 * @param limit * 分页大小,如果为-1,则返回结果集的总行数 * @return 符合查询结果的List */ public static List searchContextOneByPage(String dn, String filter, String[] returnedAtts, int start, int limit){ DirContext context = getDirContext("url","username","password"); if(context == null) return null; // 实例化一个搜索器 SearchControls constraints = new SearchControls(); // 设置搜索器的搜索范围为ONELEVEL constraints.setSearchScope( SearchControls.ONELEVEL_SCOPE); // 设置返回的属性 if (returnedAtts != null) { constraints.setReturningAttributes(returnedAtts); } try { if (filter == null || filter.trim().equals("")) { filter = "objectclass=*"; } NamingEnumeration<SearchResult> results = context.search(dn, filter, constraints); context.close(); return searchPage(results,start,limit); } catch (NamingException ex) { ex.printStackTrace(); return null; } } /** * 分页查询 * @param resultList * @param results * @throws NamingException */ private static List searchPage(NamingEnumeration<SearchResult> results,int start,int limit) throws NamingException { List resultList = new ArrayList(); int row = 0; boolean flag = false; while (results != null && results.hasMore()) { SearchResult si = results.next();// 取一个条目 if(limit == -1)//如果limit==-1,只统计总行数 row++; else { if(row++ == start) flag = true;//从start行开始取数据 Attributes attrs = si.getAttributes(); if (attrs != null && flag) { Map resultRowMap = new HashMap();// 一行数据 for (NamingEnumeration ae = attrs.getAll(); ae.hasMoreElements();) { Attribute attr = (Attribute) ae.next();// 获取一个属性 String attrId = attr.getID(); Enumeration vals = attr.getAll(); if (vals != null) { ArrayList valList = new ArrayList(); while (vals.hasMoreElements()) { Object obj = vals.nextElement(); if (obj instanceof String) { String _value = (String) obj; valList.add(_value); } else { valList.add(obj); } } resultRowMap.put(attrId, valList); } } resultList.add(resultRowMap); if(resultList.size() == limit){ break; } } } } results.close(); if(limit == -1)//如果limit为-1,则只返回总行数 resultList.add(row); return resultList; } /** * 从LDAP中取得一个连接 * @return DirContext */ private static DirContext getDirContext(String url,String userdn,String password){ Properties mEnv = new Properties(); mEnv.put(Context.AUTHORITATIVE, "true"); mEnv.put("com.sun.jndi.ldap.connect.pool", "false"); mEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); mEnv.put(Context.PROVIDER_URL, url); mEnv.put("com.sun.jndi.ldap.connect.timeout","3000"); mEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); mEnv.put(Context.SECURITY_PRINCIPAL, userdn); mEnv.put(Context.SECURITY_CREDENTIALS, password); DirContext ctx = null; try { ctx = new InitialLdapContext(mEnv, null); } catch (NamingException ex) { ex.printStackTrace(); if(ctx != null) try { ctx.close(); } catch (NamingException e) { e.printStackTrace(); } } return ctx; } }
使用时,传递start和limit作为分页的参数,这样在迭代结果集的时候进行判断,从start开始一直取limit个元素结束。
但是,这里有一个前提条件,我们要异步来统计结果集的总行数,传递limit为-1。以EXT为例,我们覆盖Ext.PagingToolbar这个类里的一些函数,保存为myPagebar.js。
(function (){ var total = 0; var T = Ext.Toolbar; Ext.PagingToolbar.prototype.setTotalCount = function(num){ total = num; } Ext.PagingToolbar.prototype.getPageData = function(){ if(total == 0){ this.inputItem.setDisabled(true); }else{ this.inputItem.setDisabled(false); this.last.setDisabled(false); } return { total : total, activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize), pages : Math.ceil(total/this.pageSize) }; } Ext.PagingToolbar.prototype.onLoad = function(store, r, o){ if(!this.rendered){ this.dsLoaded = [store, r, o]; return; } var p = this.getParams(); this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0; var d = this.getPageData(), ap = d.activePage, ps = d.pages; this.afterTextItem.setText(String.format(this.afterPageText, d.pages)); this.inputItem.setValue(ap); this.first.setDisabled(ap == 1); this.prev.setDisabled(ap == 1); this.next.setDisabled(ap == ps); //this.last.setDisabled(ap == ps); this.refresh.enable(); this.updateInfo(); this.fireEvent('change', this, d); } Ext.PagingToolbar.prototype.updateInfo = function(){ if(this.displayItem){ var count = this.store.getCount(); var msg = count == 0 ? this.emptyMsg : String.format( this.displayMsg, this.cursor+1, this.cursor+count, total ); this.displayItem.setText(msg); } } Ext.PagingToolbar.prototype.changePage = function(page){ this.doLoad(((page-1) * this.pageSize).constrain(0, total)); } Ext.PagingToolbar.prototype.moveLast = function(){ var extra = total % this.pageSize; this.doLoad(extra ? (total - extra) : total - this.pageSize); } })();
在jsp里引入myPagebar.js后,按照正常的方式使用Ext.PagingToolbar就可以了。
这样,在使用Ext.grid.GridPanel来显示数据之前,先使用Ajax去后台统计总行数,传递参数里增加start:1,limit:-1。
在Ajax成功返回后,调用Ext.PagingToolbar.prototype.setTotalCount(totalRow);同时,Ext.grid.GridPanel的store会去后台load数据,传给后台的参数包括start:1,limit:50,表示取第一页的50行数据。这样就实现了后台分页的效果。
如果数据很多,统计总行数会耗时较长,这时Ext.grid.GridPanel上显示的总页数为0,但是可以点击<下一页>,继续访问下一页的数据。直到总行数统计完成后,才能看到总页数,才能翻到最后一页。
这种方式避免了数据过多时的内存溢出问题,也提高了数据的访问速度,最起码是页数比较靠前的数据的访问速度。友好度也要好很多。
评论
2 楼
softfn
2014-01-15
没解决本质问题 你这个只是为了页面分页而已
1 楼
tangmin823
2013-02-19
这个根本算不上LDAP分页查询啊,不也是先查询出所有的记录吗?!
发表评论
-
使用zookeeper实现分布式共享锁
2013-04-13 15:59 2597分布式系统中经常需要协调多进程,多个jvm,或者多台机器之间 ... -
WebService:Axis客户端调用需要身份验证的CXF服务
2012-11-24 12:05 7070CXF服务端代码: 1、web.xml配置 < ... -
使用axis轻松调用Webservice
2012-11-10 13:15 21972使用axis1.4调用webservice有两种简单的方式: ... -
执行java程序时如何引用依赖的jar
2012-11-10 12:38 1786在执行java程序时我们可以通过-Djava.ext.dirs ... -
Log4j简单实用配置
2012-10-27 12:22 3667#A1为控制台输出,A2为文件输出,R为文件输出,并且按 ... -
JavaNIO处理长连接
2012-09-12 21:04 14124之前在IBM的网站上看到过一篇介绍NIO的文章,收获很大。但文 ... -
Int和byte数组之间的转换
2012-08-27 20:25 18807有时候和C的程序通信的时候,我们在封装协议时,可能需要将Jav ... -
用闭锁测试HashMap的并发写入问题
2012-08-27 19:39 3659今天无意中看到以前写 ... -
并行计算框架的Java实现--系列三
2012-07-14 14:38 4161接上篇并行计算框架的Java实现--系列二 优化锁,之 ... -
并行计算框架的Java实现--系列二
2012-07-14 08:41 2934接上篇并行计算框架的J ... -
并行计算框架的Java实现--系列一
2012-07-14 07:38 3496最近的工作需要统计一些复杂的报表,为了提高效率,想用多线程去实 ... -
ant初探
2012-06-29 13:38 2913前些天和同事交流,他说ant非常好用,他一直在用,学习资料共享 ... -
基于事件的 NIO 多线程服务器
2012-06-27 17:06 1264JDK1.4 的 NIO 有效解决了原有流式 IO 存在的线程 ... -
Java NIO学习
2012-06-22 22:46 0端午节加班要开发一个SocketServer,需要承载1000 ... -
httpclient访问https服务,可以信任证书
2012-06-02 00:48 6849private HttpClient initHttpClie ... -
Java或Web工程中查找配置文件
2012-06-02 00:35 1067String path = ""; URL ... -
如何获取真实的终端IP
2011-11-24 11:16 1217在有Apache做负载均衡的时候使用request.getRe ... -
MANIFEST.MF的应用以及如何读取jar包外的log4j.properties
2011-11-22 18:21 34MANIFEST.MF是jar文件的配置文件,在用eclips ... -
java实现的telnet协议
2011-10-02 17:14 7387package telnet; import j ... -
很好用的java反编译工具
2011-10-02 16:36 1239可以反编译单个文件,也可以反编译整个jar
相关推荐
标题中的“Ldap 分页问题”指的是在...总的来说,理解和正确实施LDAP分页对于优化大型目录服务的查询性能至关重要。开发者需要熟悉相关控制项,理解服务器的限制,并能够适当地调整查询策略以适应不同的环境和需求。
Spring LDAP。 官网 Spring LDAP API。 Spring LDAP 开发文档。
### 基于关系数据库的LDAP证书查询服务器的实现 #### 概述 随着网络通信技术的迅速发展,网络安全已成为互联网应用中不可忽视的关键因素。公钥基础设施(Public Key Infrastructure, PKI)作为保障网络通信安全的...
总结来说,"ldap域信息查询工具.zip"包含了一个关于如何使用LDP工具进行LDAP查询的文档和实际的LDP执行程序。通过这个工具,IT管理员可以高效地管理他们的LDAP目录,包括查询信息、调试问题和更新数据,这对于维护...
基于RuoYi框架,使用的是ruoyi前后端不分离的版本,实现对LDAP的整合 基于RuoYi框架,使用的是ruoyi前后端不分离的版本,实现对LDAP的整合 基于RuoYi框架,使用的是ruoyi前后端不分离的版本,实现对LDAP的整合 基于...
LDAP是一种基于X.500标准的子集,用于查询、浏览和修改目录服务中的信息。它提供了一种高效、灵活的方式来存储和检索大量的组织数据,如员工信息、资源分配等。本文将深入探讨如何通过LDAP查询指定目录中的所有活动...
理解并熟练掌握这些查询语句对于管理和维护基于LDAP的企业级系统至关重要。 此外,需要注意的是,虽然本文提供了多种查询方式,但在实际应用中还需要根据具体的LDAP服务器类型(如Active Directory、OpenLDAP等)...
因此,"AD域分页查询全部域用户数据"是一种优化查询效率的方法,它允许管理员分批获取用户信息,而不是一次性加载。 首先,我们需要理解AD域分页查询的工作原理。在Java中,我们可以使用JNDI(Java Naming and ...
**LDAP编辑器:连接与编辑LDAP数据** LDAP(Lightweight Directory Access Protocol)是一种轻量级目录访问协议,常用于组织和管理分布式身份信息。它提供了一种标准的方式来存储和检索用户、组、服务等对象的数据...
这些过滤器基于属性和值的比较,允许用户根据需要查找满足特定条件的对象。例如,可以查找所有名字为“张三”的用户或者所有状态为“激活”的账户。 **2. RFC2254字符串表示法** RFC2254规定了一种特殊的编码规则,...
当从LDAP数据库中检索到需要的数据后,这些数据又通过LDAP查询处理器返回给XML对象设计器,最终转换为查询者可理解的XML格式。 在实际应用中,LDAP通常用于存储和管理企业级的目录信息,如用户认证信息、用户组信息...
LDAP RFC2254LDAP查询过滤器的字符串表示法,中文版。 LDAPChina经典原创。
rar包:一个Web工程, 主要有,利用Spring-ldap对LDAP的基本操作(查询,增删改);Extjs实现的对Ldap的树状结构的显示,结构有点类似Softerra LDAP;一个测试类。 pdf:spring-ldap-reference.pdf Extjs.pdf ...
这通常涉及将SQL语句转换为LDAP过滤器,例如,"SELECT * FROM ou=People WHERE uid=john" 可能会转换为 LDAP 过滤器 "(&(objectClass=person)(uid=john))"。 **三、JSP/Servlet操作LDAP** 在Java环境中,我们可以...
该库实现以下规范: 用于基本操作进行密码修改操作解析专有名称特征: 连接到LDAP服务器(非TLS,TLS,STARTTLS) 绑定到LDAP服务器搜索条目过滤器编译/反编译分页搜索结果修改请求/响应添加请求/响应删除请求/响应...
Novell.Directory.Ldap.dll是C#编程中用于访问Directory(目录服务)或eDirectory(Novell的企业级目录服务)的重要组件,它提供了一组丰富的类和方法,使得开发者能够方便地进行目录操作,如查询、添加、删除和修改...
基于SSL的LDAP安全访问AD认证 基于SSL的LDAP安全访问AD认证是指使用SSL(Secure Sockets Layer)协议来保护LDAP(Lightweight Directory Access Protocol)协议与AD(Active Directory)的通信,使得密码在网络中...
基于Web的LDAP浏览器是一种用户友好的工具,它允许用户通过Web界面来查询、浏览和管理 Lightweight Directory Access Protocol (LDAP) 服务器的数据。这种B/S架构的应用程序通常由HTML、DHTML、Java以及LDAP等相关...
《基于LDAP统一用户管理系统的研究与应用》 在信息化时代的今天,用户管理是企业信息系统的核心环节。随着企业IT架构的日益复杂,多应用系统的并存使得用户管理变得愈发困难。为了解决这一问题,基于LDAP...