Java教程是为JDK 8编写的。本页描述的示例和实践不利用后续版本中引入的改进,并可能使用不再可用的技术。
请参阅Java语言更改了解Java SE 9及后续版本中更新的语言特性的摘要。
请参阅JDK发行说明了解有关所有JDK版本的新功能、增强功能和已删除或已弃用选项的信息。
连接创建部分描述了何时创建连接。它描述了几个Context实例可以共享同一个连接。
LDAP服务提供程序支持的另一种连接共享类型称为连接池。在这种共享类型中,LDAP服务提供程序维护一个(可能)先前使用过的连接池,并根据需要将它们分配给Context实例。当Context实例完成一个连接(关闭或垃圾回收)时,该连接会返回到池中以供将来使用。请注意,这种形式的共享是顺序的:从池中检索连接,使用连接,将连接返回到池中,然后再次从池中检索连接以供另一个Context实例使用。
连接池是按Java运行时系统维护的。对于某些情况,连接池可以显著提高性能。例如,如果使用连接池,处理包含四个引用同一LDAP服务器的搜索响应仅需要一个连接。如果没有连接池,这样的情况将需要四个单独的连接。
本课程的其余部分将更详细地描述如何使用连接池。
您可以通过向传递给初始上下文构造函数的环境属性中添加属性"com.sun.jndi.ldap.connect.pool"来请求连接池。以下是示例
。
// 设置用于创建初始上下文的环境 Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial"); // 启用连接池 env.put("com.sun.jndi.ldap.connect.pool", "true"); // 创建一个初始上下文(从池中获取连接) DirContext ctx = new InitialDirContext(env); // 使用ctx进行有用的操作 // 在完成时关闭上下文(将连接返回到池中) ctx.close(); // 将连接返回到池中 // 创建另一个初始上下文(从池中获取连接) DirContext ctx2 = new InitialDirContext(env); // 使用ctx2进行有用的操作 // 在完成时关闭上下文(将连接返回到池中) ctx2.close(); // 将连接返回到池中
此示例连续创建两个初始上下文。第二个初始上下文将重用第一个使用的连接。要运行此程序并观察连接如何检索和返回到池中,使用以下命令行。
#java -Dcom.sun.jndi.ldap.connect.pool.debug=fine UsePool
这应该会产生以下输出。
创建 com.sun.jndi.ldap.LdapClient@5d173[localhost:389] 使用 com.sun.jndi.ldap.LdapClient@5d173 {ou=ou: NewHires, objectclass=objectClass: top, organizationalUnit} 释放 com.sun.jndi.ldap.LdapClient@5d173 使用 com.sun.jndi.ldap.LdapClient@5d173 {ou=ou: People, objectclass=objectClass: top, organizationalunit} 释放 com.sun.jndi.ldap.LdapClient@5d173
您可以通过包含或省略"com.sun.jndi.ldap.connect.pool"属性来决定何时何地使用连接池,从而可以在每个上下文的基础上控制连接池。在上面的示例中,如果在创建第二个初始上下文之前从环境属性中删除此属性,则第二个初始上下文将不使用连接池。
LDAP提供程序通过应用程序的指示来跟踪连接是否正在使用。它假定保持打开上下文句柄的应用程序正在使用连接。因此,为了使LDAP提供程序能够正确管理连接池,您必须勤于在不再需要的上下文上调用Context.close()。
LDAP提供程序会自动检测和从连接池中删除错误连接。无论是否使用连接池,上下文最终出现错误连接的概率是相同的。
LDAP服务提供程序维护的连接池可能具有大小限制,详细信息请参见连接池配置部分。当启用连接池且没有可用的连接时,客户端应用程序将阻塞,等待可用的连接。您可以使用"com.sun.jndi.ldap.connect.timeout"环境属性来指定等待连接池连接的时间。如果省略此属性,应用程序将无限期等待。
这个属性还用于指定LDAP连接建立的超时时间,详细信息请参见连接创建部分。
连接池的目的是重用连接。因此,如果您计划在可能改变底层连接状态的Context实例上执行操作,则不应该为该Context实例使用连接池。例如,如果您计划在Context实例上调用Start TLS扩展操作,或者计划在初始上下文创建后更改安全相关属性(例如"java.naming.security.principal"或"java.naming.security.protocol"),则不应该为该Context实例使用连接池,因为LDAP提供程序不会跟踪任何此类状态更改。如果在这些情况下使用连接池,可能会 compromise 您的应用程序的安全性。