zTree根据LDAP树形结构数据展示到页面

页面需要展示通讯录信息,数据是存储在LDAP服务器中,使用zTree来展示通讯录信息。

LDAP中的数据如下图,树形结构是根据distinguishedName的值来分级的。

如其中的一个记录的distinguishedName为:

CN=丁XX,OU=市场部,OU=XX科技,OU=XX集团,DC=xxx,DC=com,DC=cn

155715_QKII_3010328.png

 

大体实现思路为:最初只展示第一层的节点,而后面的节点,用户点击展开时,才去请求。

这样每次只查询下一级的节点,请求比较快。

后台接口

以下是底层查询。使用org.springframework.ldap

   /**
     * 查询LDAP中当前节点的1级子节点
     * currentNodeDnPrefix,单前节点的完整DN去掉baseDN后的字符串,如完整DN为[OU=业务,OU=xxx,DC=com,DC=cn],去掉baseDN[OU=xxx,DC=com,DC=cn]后,传入OU=业务即可。为空字符串""时表示当前连接的根节点
     * 查询过滤条件为objectClass=*---查询所有条目,objectClass=person---查询人员条目
     * @param currentNodeDnPrefix
     * @return
     */
    public List<LdapUser> getSubnode4ContactTree (String currentNodeDnPrefix, int searchScope) {
        List<LdapUser> subnode = new ArrayList<>(0);

        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(searchScope); // 只查询当前节点的1级子节点

        /*AndFilter andFilter = new AndFilter();
        andFilter.and(new EqualsFilter("objectClass", "person"));*/

        // 如果直接使用andFilter.and(new EqualsFilter("objectClass", "*"))会被自动转义,就换成手动拼接了
        String filter = "objectClass=*"; // 查询所有条目

        subnode = ldapTemplate.search(currentNodeDnPrefix, filter, searchControls, new LdapUserAttributeMapper());

        return subnode;
    }

查询条件中的

SearchControls.OBJECT_SCOPE----------对应当前查询的一个OBJECT节点

SearchControls.ONELEVEL_SCOPE-------对应当前节点的下1级(仅仅1级)节点

SearchControls.SUBTREE_SCOPE---------对应当前节点的所有子节点

以下是初次加载时的接口

   /**
     * 获取通讯录根目录下的1级子目录
     * @return
     */
    public List<LdapUser> getBaseContactTree () {
        List<LdapUser> tree = new ArrayList<>(0);
        LdapUser baseNode = new LdapUser();
        
        // 查询当前根节点的DN,如OU=xxx,DC=com,DC=cn
        List<LdapUser> baseNodeList = ldapUserService.getSubnode4ContactTree("", SearchControls.OBJECT_SCOPE);
        if (baseNodeList.size() == 1) {
            baseNode = baseNodeList.get(0);
            if (!StringUtils.isEmpty(baseNodeList.get(0).getDistinguishedName())) {
                baseDN = baseNodeList.get(0).getDistinguishedName();
            }
        } else {
            return tree;
        }
        tree = ldapUserService.getSubnode4ContactTree("", SearchControls.ONELEVEL_SCOPE);
        
        // 排序,要自己实现Comparator
        Collections.sort(tree, new LdapUserComparator());
        return tree;
    }

以下是页面展开当前节点时,查询当前节点的1级子节点接口

   /**
     * 获取当前节点的1级子节点,
     * @param currentNodeDn 当前节点的完整DN
     * @return
     */
    public List<LdapUser> newContactTreeSubnode(String currentNodeDn) {
        List<LdapUser> contactTree = new ArrayList<>(0);
        if (StringUtils.isEmpty(currentNodeDn) ) {
            return contactTree;
        }

        // 查询当前节点下的1级子节点
        List<LdapUser> currentNodeSubList = ldapUserService.getSubnode4ContactTree(currentNodeDn.substring(0, currentNodeDn.indexOf(baseDN)-1), SearchControls.ONELEVEL_SCOPE);
        if (!CollectionUtils.isEmpty(currentNodeSubList)) {
            //设置CN名称
            for (LdapUser node : currentNodeSubList) {
                if (StringUtils.isEmpty(node.getCn())) {
                    node.setCn(node.getDistinguishedName().substring(node.getDistinguishedName().indexOf("=") + 1, node.getDistinguishedName().indexOf(",")));
                }
            }
            contactTree.addAll(currentNodeSubList);
            Collections.sort(contactTree, new LdapUserComparator()); // 根据displayOrder从小到大排序
        }
        return contactTree;
    }

 排序用的排序比较器

import java.util.Comparator;

/**
 * 根据displayOrder从小到大排序
 */
public class LdapUserComparator implements Comparator<LdapUser> {
    @Override
    public int compare(LdapUser o1, LdapUser o2) {
        // 从小到大
        if (o1 == null || o1.getDisplayOrder() == null ) {
            if (o2 == null || o2.getDisplayOrder() == null ) {
                return -1;
            }
            return 0;
        }
        if (o2 == null || o2.getDisplayOrder() == null ) {
            return 1;
        }
        int retval = Integer.compare(Integer.parseInt(o1.getDisplayOrder()), Integer.parseInt(o2.getDisplayOrder()));
        return retval;
    }
}

----------------------------------------------------------------------------------------------------

页面展示

展开zTree某个父节点时,查询其子节点。

          onExpand:  function zTreeOnExpand(event, treeId, treeNode) {
                    var tree = JSON.parse(window.localStorage.getItem('contactTree'));
                    var newtree;
                    $.post(baseContextPath + "/xx/xxx/subnode", {
                        currentNodeDn:treeNode.distinguishedName
                    },function(res){
                        var res = JSON.parse(res);
                        if(res && res.success){
                            var array = res.data;
                            for (var i=0;i<array.length;i++){
                                if(!array[i].mail){   //通过mail判断是否为父节点
                                    array[i].isParent = true;
                                }
                            }
                            if(treeNode.children.length==0){
                                var newNode = array;
                                var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
                                newNode = treeObj.addNodes(treeNode, newNode,false);
                            }
                        }
                    })
            }

 

 

===========================================================

而最初考虑后台使用递归查询出整个树结构,再传给页面展示。但在实现中,4个层级,不到1000的用户数据,查询所有数据用了15s左右,显然不行。

   /**
     * 递归查询数据,数据越多越慢
     * @return
     */
    public List<LdapUser> newContactTree() {
        long sTime = System.currentTimeMillis();

        List<LdapUser> tree = new ArrayList<>(0);
        LdapUser baseNode = new LdapUser();
        // 查询当前根节点的DN,如OU=xxx,DC=com,DC=cn
        List<LdapUser> baseNodeList = ldapUserService.getSubnode4ContactTree("", SearchControls.OBJECT_SCOPE);
        if (baseNodeList.size() == 1) {
            baseNode = baseNodeList.get(0);
            if (!StringUtils.isEmpty(baseNodeList.get(0).getDistinguishedName())) {
                baseDN = baseNodeList.get(0).getDistinguishedName();
            }
        } else {
            return tree;
        }

        // 递归获取1级子节点
        baseNode = getLDAPSubNodeList(baseNode);
        tree.addAll(baseNode.getChildren());

        long fTime = System.currentTimeMillis();
        System.out.println("展示通讯录消耗时间: " +(fTime - sTime)+ " ms");

        return tree;
    }

 

    // 递归获取1级子节点
    public LdapUser getLDAPSubNodeList(LdapUser fatherNode) {
        String currentNodeDnPrefix = null;
        if (baseDN.equals(fatherNode.getDistinguishedName())) {
            currentNodeDnPrefix = "";
        } else {
            currentNodeDnPrefix = fatherNode.getDistinguishedName().substring(0, fatherNode.getDistinguishedName().indexOf(baseDN)-1);
        }

        List<LdapUser> subNodeList = ldapUserService.getSubnode4ContactTree(currentNodeDnPrefix, SearchControls.ONELEVEL_SCOPE);

        if(CollectionUtils.isEmpty(subNodeList)) {
            // 已经是叶子节点,不用继续查询
        } else {
            fatherNode.setChildren(subNodeList);
            for(Iterator it = subNodeList.iterator(); it.hasNext();) {
               LdapUser node = (LdapUser) it.next();
               // 每条记录需要进行的单独处理
               // 继续查询子节点
               getLDAPSubNodeList(node);
            }
        }
        return fatherNode;
    }

 

转载于:https://my.oschina.net/u/3010328/blog/827346

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值