zoukankan      html  css  js  c++  java
  • JAVA操作LDAP总结

    一、LDAP概念

    LDAP的全称为Lightweight Directory Access Protocol(轻量级目录访问协议), 基于X.500标准, 支持 TCP/IP。

    LDAP目录为数据库,通过LDAP服务器(相当于DBMS)处理查询和更新, 以树状的层次结构来存储数据,相对关系型数据库, LDAP主要是优化数据读取的性能,适用于比较少改变、跨平台的信息。

    二、Softerra LDAP Administrator

             下载安装软件,并配置LDAP

                                    

    DN:Distinguished Name 唯一标识一条记录的路径,Base DN为基准DN,指定LDAP search的起始DN,即从哪个DN下开始搜索,RDN为叶子结点本身的名字。

    DC:Domain Component 一条记录所属区域

    OU:Organization Unit 组织单元

    CN/UID:一条记录的名字/ID

    三、在JAVA中应用LDAP

             1、spring配置文件

            <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
              <constructor-arg ref="ldapcontextSource" />
        </bean>

             <bean id="ldapcontextSource" class="org.springframework.ldap.core.support.LdapContextSource">

                       <property name="url" value="${LdapConnHost}" /> <!—例: LdapConnHost=ldap://10.190.123.123 -->

                       <property name="userDn" value="${LdapConnUser}" /><!—例: LdapConnUser=cn=root -->

                       <property name="password" value="${LdapConnPwd}" /><!—例: LdapConnPwd=111111 -->

                       <property name="base" value="${LdapBaseDn}" /> <!—Base DN 例: LdapBaseDn=DC=FJTIC -->

                       <property name="pooled" value="false" />

             </bean>

            

             2、JAVA代码

      1 package com.test.dao;
      2 
      3 import java.beans.PropertyDescriptor;
      4 import java.lang.reflect.Field;
      5 import java.lang.reflect.InvocationTargetException;
      6 import java.lang.reflect.Method;
      7 import java.util.ArrayList;
      8 import java.util.List;
      9 import javax.naming.Name;
     10 import javax.naming.NamingEnumeration;
     11 import javax.naming.NamingException;
     12 import javax.naming.directory.Attribute;
     13 import javax.naming.directory.Attributes;
     14 import javax.naming.directory.BasicAttribute;
     15 import javax.naming.directory.BasicAttributes;
     16 import javax.naming.directory.ModificationItem;
     17 import org.apache.commons.beanutils.BeanUtils;
     18 import org.springframework.beans.factory.annotation.Autowired;
     19 import org.springframework.dao.EmptyResultDataAccessException;
     20 import org.springframework.ldap.core.ContextMapper;
     21 import org.springframework.ldap.core.DirContextAdapter;
     22 import org.springframework.ldap.core.DirContextOperations;
     23 import org.springframework.ldap.core.DistinguishedName;
     24 import org.springframework.ldap.core.LdapTemplate;
     25 import org.springframework.ldap.core.support.AbstractContextMapper;
     26 import org.springframework.ldap.filter.AndFilter;
     27 import org.springframework.ldap.filter.EqualsFilter;
     28 import org.springframework.ldap.filter.OrFilter;
     29 import org.springframework.stereotype.Component;
     30 import com.surekam.model.Person;
     31 import com.surekam.utils.DateCl;
     32 import com.surekam.utils.StringUtil;
     33 
     34 @Component
     35 public class UserDAOL {
     36     @Autowired
     37     private LdapTemplate ldapTemplate;
     38 
     39     /**
     40      *
     41      * @Description: 添加
     42      *
     43      */
     44     public boolean addPerson(Person person) {
     45         boolean flag = false;
     46         Name dn = buildUDn(person.getUid());
     47         Attributes buildAddAttributes = buildAddAttributes(person);
     48         ldapTemplate.bind(dn, null, buildAddAttributes);
     49         flag = true;
     50         return flag;
     51     }
     52 
     53     /**
     54      *
     55      * @Description: 修改
     56      *
     57      */
     58     public boolean updatePerson(Person person) {
     59         boolean flag = false;
     60         Name dn = buildUDn(person.getUid());
     61         ModificationItem[] modificationItem = buildModifyAttributes(person);
     62         ldapTemplate.modifyAttributes(dn, modificationItem);
     63         flag = true;
     64         return flag;
     65     }
     66 
     67     /**
     68      *
     69      * 多条件获取用户
     70      * 
     71      */
     72     public List<Person> getPersonByOu(String ou, String level) {
     73         AndFilter filter = new AndFilter();
     74         OrFilter orFilter1 = new OrFilter();
     75         if ("处级干部".equals(level)) {
     76             orFilter1.or(new EqualsFilter("cuadministrativelevels", "aa"));
     77             orFilter1.or(new EqualsFilter("cuadministrativelevels", "bb"));
     78             orFilter1.or(new EqualsFilter("cuadministrativelevels", "cc"));
     79             orFilter1.or(new EqualsFilter("cuadministrativelevels", "dd"));
     80         }
     81         if ("普通员工".equals(level)) {
     82             orFilter1.or(new EqualsFilter("cuadministrativelevels", "ee"));
     83             orFilter1.or(new EqualsFilter("cuadministrativelevels", "ff"));
     84             orFilter1.or(new EqualsFilter("cuadministrativelevels", "gg"));
     85         }
     86         OrFilter orFilter2 = new OrFilter();
     87         orFilter2.or(new EqualsFilter("departmentnumber", ou));
     88         orFilter2.or(new EqualsFilter("cutransferdnumber", ou));
     89         filter.and(orFilter2);
     90         filter.and(orFilter1);
     91         System.out.println(filter.toString());
     92         List<Person> list = ldapTemplate.search("cn=users,dc=hq", filter
     93                 .encode(), new PersonContextMapper());
     94         return list;
     95     }
     96 
     97 
     98     /**
     99      *
    100      * 生成用户DN
    101      * 
    102      * @return uid=123455,cn=users,dc=hq
    103      */
    104     private Name buildUDn(String urdn) {
    105         DistinguishedName dn = new DistinguishedName("");
    106         dn.add("dc", "hq");
    107         dn.add("cn", "users");
    108         dn.add("uid", urdn);
    109         return dn;
    110     }
    111 
    112     /**
    113      *
    114      * 组织查询结果
    115      * 
    116      */
    117     public static class PersonContextMapper implements ContextMapper {
    118         public Object mapFromContext(Object ctx) {
    119             if (ctx == null)
    120                 return new Person();
    121             DirContextAdapter context = (DirContextAdapter) ctx;
    122             Person per = new Person();
    123             Attributes attrs = context.getAttributes();
    124             NamingEnumeration results = attrs.getAll();
    125             Class c = per.getClass();
    126             while (results.hasMoreElements()) {
    127                 try {
    128                     Attribute attr = (Attribute) results.next();
    129                     String value = attr.get().toString();
    130                     if (StringUtil.isNotEmpty(value)) {
    131                         String fieldName = attr.getID();
    132                         if ("objectclass".equals(fieldName.toLowerCase())) {
    133                             continue;
    134                         }
    135                         Field field = c.getDeclaredField(fieldName
    136                                 .toLowerCase());
    137                         Class fieldClazz = field.getType();
    138                         /*
    139                          * 如果属性条数大于1,那就是多值属性 attr.getAttributeDefinition()
    140                          * 获取多值属性的方法没找到
    141                          */
    142                         if (fieldClazz.isAssignableFrom(List.class)) { // 属性值数大于1
    143                             NamingEnumeration values = attr.getAll(); // 获取所有值
    144                             // LDAP中的多值属性只会是String类型
    145                             List<String> list = new ArrayList<String>();
    146                             while (values.hasMoreElements()) {
    147                                 list.add(values.next().toString());
    148                             }
    149                             BeanUtils.setProperty(per, fieldName.toLowerCase(),
    150                                     list);
    151                         } else {
    152                             // 普通属性
    153                             BeanUtils.setProperty(per, fieldName.toLowerCase(),
    154                                     value);
    155                         }
    156                     }
    157                 } catch (IllegalAccessException e) {
    158                     e.printStackTrace();
    159                 } catch (InvocationTargetException e) {
    160                     e.printStackTrace();
    161                 } catch (NamingException e) {
    162                     e.printStackTrace();
    163                 } catch (SecurityException e) {
    164                     // TODO Auto-generated catch block
    165                     e.printStackTrace();
    166                 } catch (NoSuchFieldException e) {
    167                     // TODO Auto-generated catch block
    168                     e.printStackTrace();
    169                 }
    170             }
    171             per.setDn(context.getNameInNamespace());
    172             return per;
    173         }
    174     }
    175 
    176     /**
    177      *
    178      * 组织添加数据数据
    179      * 
    180      */
    181     @SuppressWarnings("unchecked")
    182     private Attributes buildAddAttributes(Person p) {
    183         Attributes attrs = new BasicAttributes();
    184         BasicAttribute ocattr = new BasicAttribute("objectclass");
    185         ocattr.add("top");
    186         ocattr.add("person");
    187         ocattr.add("organizationalPerson");
    188         ocattr.add("inetOrgPerson");
    189         ocattr.add("FJTicPerson");
    190         attrs.put(ocattr);
    191         Class c = p.getClass();
    192         Field[] fields = c.getDeclaredFields();
    193         for (int i = 0; i < fields.length; i++) {
    194             try {
    195                 Class fieldClazz = fields[i].getType();
    196                 String fieldName = fields[i].getName(); // 获得属性名
    197                 String fieldVlue = BeanUtils.getProperty(p, fieldName); // 获得属性值
    198                 /*
    199                  * 判断属性是否要过滤,例如修改时间之类的字段LDAP是没有的 判断属性值是否为空,在这里过滤了所有null和""
    200                  * 增加操作中不存在主动设置某个值为空的情况 所以只需要处理有值属性
    201                  */
    202                 if (checkfieldName(fieldName) || StringUtil.isEmpty(fieldVlue))
    203                     continue;
    204                 /*
    205                  * 多值属性的处理 如果多值属性为空,那么增加的时候就不会增加值进去
    206                  */
    207                 if (fieldClazz.isAssignableFrom(List.class)) { // 集合属性
    208                     BasicAttribute ocattr1 = new BasicAttribute(fieldName);
    209                     PropertyDescriptor pd = new PropertyDescriptor(fieldName, c);
    210                     Method getMethod = pd.getReadMethod();// 获得get方法
    211                     List list = (List) getMethod.invoke(p);// 执行get方法返回一个Object
    212                     for (Object object : list) {
    213                         ocattr1.add(object);
    214                     }
    215                     attrs.put(ocattr1);
    216                 } else {
    217                     attrs.put(fieldName, fieldVlue);
    218                 }
    219             } catch (Exception e) {
    220                 e.printStackTrace();
    221             }
    222         }
    223         return attrs;
    224 
    225     }
    226 
    227     /**
    228      *
    229      * 组织修改数据
    230      * 
    231      */
    232     @SuppressWarnings("unchecked")
    233     private ModificationItem[] buildModifyAttributes(Person p) {
    234         ArrayList<ModificationItem> attrs = new ArrayList<ModificationItem>();
    235         Class c = p.getClass();
    236         Field[] fields = c.getDeclaredFields();
    237         for (Field field : fields) {
    238             try {
    239                 Class fieldClazz = field.getType();
    240                 String fieldName = field.getName(); // 获得属性名
    241                 String fieldValue = BeanUtils.getProperty(p, fieldName);
    242                 /*
    243                  * 判断属性是否要过滤,例如修改时间之类的字段LDAP是没有的 判断属性值是否为空,在这里过滤了所有null和""
    244                  * 要置空的属性通过识别特殊属性值:delAtr 在后面做重新置空操作
    245                  */
    246                 if (checkfieldName(fieldName) || StringUtil.isEmpty(fieldValue))
    247                     continue;
    248                 BasicAttribute basicAttr = new BasicAttribute(fieldName);
    249                 /*
    250                  * 多值属性的处理 如果传递一个空的list,那么修改的时候就会清空多值属性 (new ArrayList<String>())
    251                  */
    252                 if (fieldClazz.isAssignableFrom(List.class)) { // 如果是集合属性
    253                     PropertyDescriptor pd = new PropertyDescriptor(fieldName, c);
    254                     Method getMethod = pd.getReadMethod();// 获得get方法
    255                     List list = (List) getMethod.invoke(p);// 执行get方法返回一个Object
    256                     for (Object object : list) {
    257                         basicAttr.add(object);
    258                     }
    259                 } else {
    260                     /*
    261                      * 判断删除标记来对值进行置空 传递过来的对象中有些属性没有做修改就传递了"" 有些是要修改为 ""
    262                      * 所以在上面要过滤所有 "" 属性,避免将不修改的参数全都置空了 然后通过识别要修改参数的特有值来判断是否主动置空
    263                      * 如果add一个""进去,那么在LDAP中依然会显示
    264                      * 如果不给值,由BasicAttribute自动授予空值,那么在LDAP中就不显示了
    265                      */
    266                     if ("delAtr".equals(fieldValue)) {
    267                         basicAttr.add(""); // 置空属性
    268                     } else {
    269                         basicAttr.add(fieldValue);// 有值属性
    270                     }
    271                 }
    272                 // 替换条目
    273                 attrs.add(new ModificationItem(
    274                         DirContextAdapter.REPLACE_ATTRIBUTE, basicAttr));
    275             } catch (Exception e) {
    276                 e.printStackTrace();
    277             }
    278         }
    279         return attrs.toArray(new ModificationItem[attrs.size()]);
    280     }
    281 
    282     /**
    283      *
    284      * 过滤默认值字段
    285      * 
    286      */
    287     private static boolean checkfieldName(String fieldName) {
    288         String[] check = new String[] { "id", "status", "createtime",
    289                 "updatetime", "dn" };
    290         for (int i = 0; i < check.length; i++) {
    291             if (check[i].equalsIgnoreCase(fieldName))
    292                 return true;
    293         }
    294         return false;
    295     }
    296 }
    spring版
      1 package com.smnpc.util;
      2 
      3 import java.util.Hashtable;
      4 import java.util.Vector;
      5 
      6 import javax.naming.Context;
      7 import javax.naming.NamingEnumeration;
      8 import javax.naming.NamingException;
      9 import javax.naming.directory.Attribute;
     10 import javax.naming.directory.Attributes;
     11 import javax.naming.directory.BasicAttribute;
     12 import javax.naming.directory.BasicAttributes;
     13 import javax.naming.directory.DirContext;
     14 import javax.naming.directory.InitialDirContext;
     15 import javax.naming.directory.ModificationItem;
     16 import javax.naming.directory.SearchControls;
     17 import javax.naming.directory.SearchResult;
     18 import javax.naming.ldap.LdapContext;
     19 
     20 /**
     21  * Java通过Ldap操作AD的增删该查询
     22  * 
     23  * @author guob
     24  */
     25 
     26 public class LdapbyUser {
     27     DirContext dc = null;
     28     String root = "dc=example,dc=com"; // LDAP的根节点的DC
     29 
     30     /**
     31      * 
     32      * @param dn类似于"CN=RyanHanson,dc=example,dc=com"
     33      * @param employeeID是Ad的一个员工号属性
     34      */
     35     public LdapbyUser(String dn, String employeeID) {
     36         init();
     37         // add();//添加节点
     38         // delete("ou=hi,dc=example,dc=com");//删除"ou=hi,dc=example,dc=com"节点
     39         // renameEntry("ou=new,o=neworganization,dc=example,dc=com","ou=neworganizationalUnit,o=neworganization,dc=example,dc=com");//重命名节点"ou=new,o=neworganization,dc=example,dc=com"
     40         // searchInformation("dc=example,dc=com", "",
     41         // "sAMAccountName=guob");//遍历所有根节点
     42         modifyInformation(dn, employeeID);// 修改
     43         // Ldapbyuserinfo("guob");//遍历指定节点的分节点
     44         close();
     45     }
     46 
     47     /**
     48      * 
     49      * Ldap连接
     50      * 
     51      * @return LdapContext
     52      */
     53     public void init() {
     54         Hashtable env = new Hashtable();
     55         String LDAP_URL = "ldap://xxxx:389"; // LDAP访问地址
     56         String adminName = "example\\user"; // 注意用户名的写法:domain\User或
     57         String adminPassword = "userpassword"; // 密码
     58         env.put(Context.INITIAL_CONTEXT_FACTORY,
     59                 "com.sun.jndi.ldap.LdapCtxFactory");
     60         env.put(Context.PROVIDER_URL, LDAP_URL);
     61         env.put(Context.SECURITY_AUTHENTICATION, "simple");
     62         env.put(Context.SECURITY_PRINCIPAL, adminName);
     63         env.put(Context.SECURITY_CREDENTIALS, adminPassword);
     64         try {
     65             dc = new InitialDirContext(env);// 初始化上下文
     66             System.out.println("认证成功");// 这里可以改成异常抛出。
     67         } catch (javax.naming.AuthenticationException e) {
     68             System.out.println("认证失败");
     69         } catch (Exception e) {
     70             System.out.println("认证出错:" + e);
     71         }
     72     }
     73 
     74     /**
     75      * 添加
     76      */
     77     public void add(String newUserName) {
     78         try {
     79             BasicAttributes attrs = new BasicAttributes();
     80             BasicAttribute objclassSet = new BasicAttribute("objectClass");
     81             objclassSet.add("sAMAccountName");
     82             objclassSet.add("employeeID");
     83             attrs.put(objclassSet);
     84             attrs.put("ou", newUserName);
     85             dc.createSubcontext("ou=" + newUserName + "," + root, attrs);
     86         } catch (Exception e) {
     87             e.printStackTrace();
     88             System.out.println("Exception in add():" + e);
     89         }
     90     }
     91 
     92     /**
     93      * 删除
     94      * 
     95      * @param dn
     96      */
     97     public void delete(String dn) {
     98         try {
     99             dc.destroySubcontext(dn);
    100         } catch (Exception e) {
    101             e.printStackTrace();
    102             System.out.println("Exception in delete():" + e);
    103         }
    104     }
    105 
    106     /**
    107      * 重命名节点
    108      * 
    109      * @param oldDN
    110      * @param newDN
    111      * @return
    112      */
    113     public boolean renameEntry(String oldDN, String newDN) {
    114         try {
    115             dc.rename(oldDN, newDN);
    116             return true;
    117         } catch (NamingException ne) {
    118             System.err.println("Error: " + ne.getMessage());
    119             return false;
    120         }
    121     }
    122 
    123     /**
    124      * 修改
    125      * 
    126      * @return
    127      */
    128     public boolean modifyInformation(String dn, String employeeID) {
    129         try {
    130             System.out.println("updating...\n");
    131             ModificationItem[] mods = new ModificationItem[1];
    132             /* 修改属性 */
    133             // Attribute attr0 = new BasicAttribute("employeeID", "W20110972");
    134             // mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
    135             // attr0);
    136             /* 删除属性 */
    137             // Attribute attr0 = new BasicAttribute("description",
    138             // "陈轶");
    139             // mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
    140             // attr0);
    141             /* 添加属性 */
    142             Attribute attr0 = new BasicAttribute("employeeID", employeeID);
    143             mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr0);
    144             /* 修改属性 */
    145             dc.modifyAttributes(dn + ",dc=example,dc=com", mods);
    146             return true;
    147         } catch (NamingException e) {
    148             e.printStackTrace();
    149             System.err.println("Error: " + e.getMessage());
    150             return false;
    151         }
    152     }
    153 
    154     /**
    155      * 关闭Ldap连接
    156      */
    157     public void close() {
    158         if (dc != null) {
    159             try {
    160                 dc.close();
    161             } catch (NamingException e) {
    162                 System.out.println("NamingException in close():" + e);
    163             }
    164         }
    165     }
    166 
    167     /**
    168      * @param base
    169      *            :根节点(在这里是"dc=example,dc=com")
    170      * @param scope
    171      *            :搜索范围,分为"base"(本节点),"one"(单层),""(遍历)
    172      * @param filter
    173      *            :指定子节点(格式为"(objectclass=*)",*是指全部,你也可以指定某一特定类型的树节点)
    174      */
    175     public void searchInformation(String base, String scope, String filter) {
    176         SearchControls sc = new SearchControls();
    177         if (scope.equals("base")) {
    178             sc.setSearchScope(SearchControls.OBJECT_SCOPE);
    179         } else if (scope.equals("one")) {
    180             sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
    181         } else {
    182             sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
    183         }
    184         NamingEnumeration ne = null;
    185         try {
    186             ne = dc.search(base, filter, sc);
    187             // Use the NamingEnumeration object to cycle through
    188             // the result set.
    189             while (ne.hasMore()) {
    190                 System.out.println();
    191                 SearchResult sr = (SearchResult) ne.next();
    192                 String name = sr.getName();
    193                 if (base != null && !base.equals("")) {
    194                     System.out.println("entry: " + name + "," + base);
    195                 } else {
    196                     System.out.println("entry: " + name);
    197                 }
    198 
    199                 Attributes at = sr.getAttributes();
    200                 NamingEnumeration ane = at.getAll();
    201                 while (ane.hasMore()) {
    202                     Attribute attr = (Attribute) ane.next();
    203                     String attrType = attr.getID();
    204                     NamingEnumeration values = attr.getAll();
    205                     Vector vals = new Vector();
    206                     // Another NamingEnumeration object, this time
    207                     // to iterate through attribute values.
    208                     while (values.hasMore()) {
    209                         Object oneVal = values.nextElement();
    210                         if (oneVal instanceof String) {
    211                             System.out.println(attrType + ": "
    212                                     + (String) oneVal);
    213                         } else {
    214                             System.out.println(attrType + ": "
    215                                     + new String((byte[]) oneVal));
    216                         }
    217                     }
    218                 }
    219             }
    220         } catch (Exception nex) {
    221             System.err.println("Error: " + nex.getMessage());
    222             nex.printStackTrace();
    223         }
    224     }
    225 
    226     /**
    227      * 查询
    228      * 
    229      * @throws NamingException
    230      */
    231     public void Ldapbyuserinfo(String userName) {
    232         // Create the search controls
    233         SearchControls searchCtls = new SearchControls();
    234         // Specify the search scope
    235         searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    236         // specify the LDAP search filter
    237         String searchFilter = "sAMAccountName=" + userName;
    238         // Specify the Base for the search 搜索域节点
    239         String searchBase = "DC=example,DC=COM";
    240         int totalResults = 0;
    241         String returnedAtts[] = { "url", "whenChanged", "employeeID", "name",
    242                 "userPrincipalName", "physicalDeliveryOfficeName",
    243                 "departmentNumber", "telephoneNumber", "homePhone", "mobile",
    244                 "department", "sAMAccountName", "whenChanged", "mail" }; // 定制返回属性
    245 
    246         searchCtls.setReturningAttributes(returnedAtts); // 设置返回属性集
    247 
    248         // searchCtls.setReturningAttributes(null); // 不定制属性,将返回所有的属性集
    249 
    250         try {
    251             NamingEnumeration answer = dc.search(searchBase, searchFilter,
    252                     searchCtls);
    253             if (answer == null || answer.equals(null)) {
    254                 System.out.println("answer is null");
    255             } else {
    256                 System.out.println("answer not null");
    257             }
    258             while (answer.hasMoreElements()) {
    259                 SearchResult sr = (SearchResult) answer.next();
    260                 System.out
    261                         .println("************************************************");
    262                 System.out.println("getname=" + sr.getName());
    263                 Attributes Attrs = sr.getAttributes();
    264                 if (Attrs != null) {
    265                     try {
    266 
    267                         for (NamingEnumeration ne = Attrs.getAll(); ne
    268                                 .hasMore();) {
    269                             Attribute Attr = (Attribute) ne.next();
    270                             System.out.println("AttributeID="
    271                                     + Attr.getID().toString());
    272                             // 读取属性值
    273                             for (NamingEnumeration e = Attr.getAll(); e
    274                                     .hasMore(); totalResults++) {
    275                                 String user = e.next().toString(); // 接受循环遍历读取的userPrincipalName用户属性
    276                                 System.out.println(user);
    277                             }
    278                             // System.out.println(" ---------------");
    279                             // // 读取属性值
    280                             // Enumeration values = Attr.getAll();
    281                             // if (values != null) { // 迭代
    282                             // while (values.hasMoreElements()) {
    283                             // System.out.println(" 2AttributeValues="
    284                             // + values.nextElement());
    285                             // }
    286                             // }
    287                             // System.out.println(" ---------------");
    288                         }
    289                     } catch (NamingException e) {
    290                         System.err.println("Throw Exception : " + e);
    291                     }
    292                 }
    293             }
    294             System.out.println("Number: " + totalResults);
    295         } catch (Exception e) {
    296             e.printStackTrace();
    297             System.err.println("Throw Exception : " + e);
    298         }
    299     }
    300 
    301     /**
    302      * 主函数用于测试
    303      * 
    304      * @param args
    305      */
    306     public static void main(String[] args) {
    307         new LdapbyUser("CN=RyanHanson", "bbs.it-home.org");
    308     }
    309 }
    普通实现(转载)
  • 相关阅读:
    raw_input() 与 input()对比
    你很熟悉CSS,却没掌握这些CSS技巧
    CSS样式设置
    javascript基本语法和变量(转)
    手机/移动前端开发需要注意的20个要点
    移动端”宴席知多少
    git第一次提交代码到远程仓库
    java对过反射调用方法
    站点收集
    别人抢红包,我们研究一下红包算法
  • 原文地址:https://www.cnblogs.com/Nadim/p/4681003.html
Copyright © 2011-2022 走看看