我必须实现基于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的连接太多了......
所以,这是我的问题:访问这些方法的最优雅/最智能的方法是什么?
提前谢谢: - )
答案 0 :(得分:1)
由于您已经在使用Spring,我建议您使用Spring LDAP:
Spring LDAP是一个Java库,用于根据Spring的JdbcTemplate模式简化LDAP操作。该框架减轻了用户的常见杂务,例如查找和关闭上下文,循环结果,编码/解码值和过滤器等等。
特别是如果您不熟悉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>
然后,您可以在需要执行LDAP操作的地方使用LdapTemplate
:
return ldapTemplate.search(
"", "(objectclass=person)",
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
答案 1 :(得分:0)
有几种方法可以连接到ldap。使用javax.naming。*就是其中之一。在javadoc中,您可能会发现,SPI提供程序中的类管理它们自己的连接,因此您不关心它 - 这可能是您的问题的答案 - 请参阅JDK doc以及Context如何管理连接和网络 - { {3}}。
如果您习惯于更多类似JDBC的访问,则可以根据自己的喜好找到http://docs.oracle.com/javase/6/docs/api/javax/naming/ldap/LdapContext.html。在那里你有完全在你控制之下的连接,你可以像在JDBC中一样对待它们。您可以使用任何您喜欢的池库。
答案 2 :(得分:0)
不知道具体要求我将核心问题解释为“何时打开/关闭连接”。
我的水晶球告诉我你可能想要使用连接池。是的,您不会显式关闭连接,因为这是由池处理的,但这可能适合您的任务。这很容易:
// Enable connection pooling
env.put("com.sun.jndi.ldap.connect.pool", "true");
答案 3 :(得分:0)
...
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(回调)调用回调。