2013-01-05 86 views
0

我必须实现一个基于Spring的Web应用程序,允许用户管理LDAP数据。与LDAP的连接只能使用JNDI框架完成(不允许使用SpringLDAP)。从Spring连接LDAP

为此,我实现了一个工具类来完成基本操作(添加,更新,删除,列表...)。

下面是这个类的代码短块:

public class LdapUtility { 


    private static LdapUtility instance; 

    private DirContext dirContext; 


    public static LdapUtility getInstance() { 

     if(LdapUtility.instance == null) 
      LdapUtility.instance = new LdapUtility(); 

     return LdapUtility.instance; 
    } 

    /** 
    * Connect to the LDAP 
    */ 
    private LdapUtility() { 

     Hashtable env = new Hashtable(); 
     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=Manager,dc=my-domain,dc=com"); 
     env.put(Context.SECURITY_CREDENTIALS, "secret"); 

     try { 
      dirContext = new InitialDirContext(env); 
     } 
     catch(Exception ex) { 
      dirContext = null; 
     } 
    } 

    public void addUser(User u) { 

      dirContext.createSubcontext(....); //add user in the LDAP 
    } 
} 

有了这个代码,我可以通过调用LdapUtility.getInstance()...访问我的所有方法,但对LDAP连接将永远不会被释放。

另一种方法是连接到每个操作之前的LDAP,但在这种情况下,就可以到LDAP太多连接...

所以,这里是我的问题:什么是最优雅/最聪明的方式来访问这些方法?

预先感谢您:-)

回答

0

有几种方法可以连接到ldap。使用javax.naming。*就是其中之一。在javadoc中,您可能会发现,SPI提供程序中的类管理自己的连接,因此您不关心它 - 这可能是您的问题的答案 - 请参阅JDK doc以及Context如何管理连接和网络 - http://docs.oracle.com/javase/6/docs/api/javax/naming/ldap/LdapContext.html

如果您习惯于更多类似JDBC的访问,您可能会发现http://www.openldap.org/jldap/更符合您的喜好。在你的控制下,你完全可以完成连接,你可以像在JDBC中一样对待它们。您可以使用任何您喜欢的共享库。

+0

问题不在于用于连接到ldap的方式。就我而言,我必须使用JNDI(这是一个类项目)。我的问题是如何从我的控制器访问我的班级方法,同时聪明地管理ldap连接。 – user1901206

1

既然你已经使用Spring,我会建议使用Spring LDAP

春天LDAP是一个Java库,用于简化LDAP操作,基于Spring的JdbcTemplate的格局。该框架为用户解除了常见的杂事,如查找和关闭上下文,循环遍历结果,编码/解码值和过滤器等等。

尤其是如果您不熟悉LDAP和潜在的性能问题,它可以帮助开始使用这样的实用程序库,它将为您完成所有繁重的工作。

您在Spring配置配置LDAP连接设置:

<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource"> 
    <property name="url" value="ldap://localhost:389" /> 
    <property name="base" value="dc=example,dc=com" /> 
    <property name="userDn" value="cn=Manager" /> 
    <property name="password" value="secret" /> 
</bean> 

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

然后,您可以只使用LdapTemplate无论你需要执行一个LDAP操作:

return ldapTemplate.search(
    "", "(objectclass=person)", 
    new AttributesMapper() { 
     public Object mapFromAttributes(Attributes attrs) 
      throws NamingException { 
      return attrs.get("cn").get(); 
     } 
    }); 
0

不知道确切的要求我将核心问题解释为“何时打开/关闭连接”。

我的水晶球告诉我你可能想要使用连接池。诚然,你并没有明确地关闭连接,因为这是由池处理的,但这对你的任务可能没问题。这也很容易:

// Enable connection pooling 
env.put("com.sun.jndi.ldap.connect.pool", "true"); 

complete source codeOracle's basic LDAP tutorial被引用。

0

无弹簧(被禁止的),我会很快实现一些呈三角:

  • (懒惰时)创建一个简单的回调接口(比如你可以在Spring中找到 - JpaCallback.execute(EntityManager的em)) - 但对于LDAP - MyLdapCallback.execute(LdapConnection连接) - LdapConnection的intead,您可以想象任何您需要的东西 - 来自OpenLdap或SDK上下文的对象。喜欢的东西(只是为了演示):
... 
interface LdapCallback<T> { 
    T execute(DirContext ctx) throws NamingException, IOException; 
} 
... 
private <T> T execute(LdapCallback<T> callback) throws NamingException, IOException { 
    T result = null; 
    LdapContext ctx = new InitialLdapContext(); 
    try { 
     result = callback.execute(ctx); 
    } finally { 
     if (tls != null) { 
      tls.close(); 
     } 
     ctx.close(); 
    } 
    return result; 
} 
... 

完成后,您会为每个LDAP匿名类调用调用回调执行通过(回调)。

  • (有更多的时间)实现广告1 +创建AOP抚慰我的标有注释的方法与将自身执行上述包装中的我的方法(没有明确地这样做在我的代码)方面