2013-01-05 87 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撫慰我的標有註釋的方法與將自身執行上述包裝中的我的方法(沒有明確地這樣做在我的代碼)方面