0

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

为此,我实现了一个实用程序类来执行基本操作(添加、更新、删除、列表……)。

这是该类的一小段代码:

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 的连接会太多......

所以,这是我的问题:访问这些方法的最优雅/最智能的方式是什么?

先感谢您 :-)

4

4 回答 4

1

没有弹簧(被禁止),我会很快实现类似的东西:

  • (懒惰的时候)创建一个简单的回调接口(比如你可以在 spring 中找到——JpaCallback.execute(EntityManager em))——但是对于 LDAP——MyLdapCallback.execute(LdapConnection connection)——你可以想象 LdapConnection您需要的任何东西——来自 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 调用创建匿名类,并通过 execute(callback) 调用回调。

  • (有更多时间)实现广告 1. + 创建 AOP,它将用注释包装我的方法,其本身将在上面的包装器中执行我的方法(在我的代码中没有明确地这样做)
于 2013-01-07T10:38:17.470 回答
1

由于您已经在使用 Spring,我建议您使用Spring LDAP

Spring LDAP 是一个 Java 库,用于简化 LDAP 操作,基于 Spring 的 JdbcTemplate 模式。该框架减轻了用户的日常琐事,例如查找和关闭上下文、循环结果、编码/解码值和过滤器等等。

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

您在 spring config 中配置 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();
        }
     });
于 2013-01-05T17:02:29.687 回答
0

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

我的水晶球告诉我你可能想要使用连接池。诚然,您不会明确关闭连接,因为这是由池处理的,但这对于您的分配可能没问题。这很容易:

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

Oracle 的基本 LDAP 教程中引用了完整的源代码

于 2013-01-05T21:43:10.360 回答
0

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

如果您习惯于更多类似 JDBC 的访问,您可能会发现http://www.openldap.org/jldap/更符合您的喜好。在那里,您可以完全控制连接,并以与 JDBC 中相同的方式对待它们。你可以使用任何你喜欢的池化库。

于 2013-01-05T15:16:55.413 回答