文档

Java™ 教程
隐藏目录
连接池
目录: Java命名和目录接口
课程: 高级主题:LDAP用户
部分: 连接管理

连接池

连接创建部分描述了何时创建连接。它描述了几个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 您的应用程序的安全性。


上一页:关闭
下一页:配置