问题
I have to realize a web application based on Spring, allowing the user to manage LDAP data. The connection to the LDAP should be done only with the JNDI framework (no SpringLDAP allowed).
For this, I realized a utility class to do the basic operations (add, update, delete, list, ...).
Here is a short block of code of this class :
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
}
}
With this code, I can access all my methods by calling LdapUtility.getInstance()...
, but the connection to the LDAP will never be released.
Another way would be to connect to the LDAP before each operation, but in this case there would be too much connections to the LDAP...
So, here is my question : what is the most elegant/smartest way to access these methods ?
Thank you in advance :-)
回答1:
Since you're already using Spring, I would recommend using Spring LDAP:
Spring LDAP is a Java library for simplifying LDAP operations, based on the pattern of Spring's JdbcTemplate. The framework relieves the user of common chores, such as looking up and closing contexts, looping through results, encoding/decoding values and filters, and more.
Especially if you're not familiar with LDAP and potential performance problems, it can help to start of using a utility library like this that will do all the heavy lifting for you.
You configure the LDAP connection settings in the spring config:
<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>
You can then just use the LdapTemplate
wherever you need to perform an LDAP action:
return ldapTemplate.search(
"", "(objectclass=person)",
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
回答2:
There are several ways to connect to ldap. Using javax.naming.* is one of them. In javadoc you may find, that classes in your SPI provider manages their own connections, so you don't care for it -- that may be an answer to your question -- see JDK doc and how Context manages conections and network -- http://docs.oracle.com/javase/6/docs/api/javax/naming/ldap/LdapContext.html .
If you are accustomed to more JDBC-like access, you may find http://www.openldap.org/jldap/ more to your liking. There you have conections completely under your control and you treat them much the same way as in JDBC. You may use any pooling library you like.
回答3:
Not knowing the exact requirements I interpret the core question as being "when to open/close the connection".
My crystal ball tells me you may want to use a connection pool. True, you don't close the connection explicitly as this is handled by the pool but this may be ok for your assignment. It's fairly easy:
// Enable connection pooling
env.put("com.sun.jndi.ldap.connect.pool", "true");
The complete source code is referenced in Oracle's basic LDAP tutorial.
回答4:
without a spring (being forbidden), i would quickly implement something simillar:
- (when being lazy) create a simple callback interface (such as you can find in spring -- JpaCallback.execute(EntityManager em)) -- but for LDAP -- MyLdapCallback.execute(LdapConnection connection) -- intead of LdapConnection you can imagine anything you require -- objects from OpenLdap or SDK Context. Something like (just for presentation):
...
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;
}
...
Once done, you will create anonymous classes for each Ldap call an call the callback via execute(callback).
- (having more time) implement ad 1. + create AOP that will wrap my methods marked with annotation with aspect that will itself execute my methods within the wrapper above (without explicitly doing so in my code)
来源:https://stackoverflow.com/questions/14172588/connect-ldap-from-spring