如果我有50个用户,如何在应用程序中为一个用户获得一个JDBC连接

时间:2019-01-21 17:36:38

标签: java jsp servlets jdbc

我正在Web应用程序中创建一个jdbc连接。假设有50位用户将使用该应用程序。目前,我的应用程序为单个用户建立了20多个连接。如何提高性能?

public class AuditConnection 
{
private static String URL = 
"jdbc:postgresql://localhost:5432/MDM_Audit? 
user=rajan&password=rajan";

private static String driverName = "org.postgresql.Driver";   

private static Connection con;

public static Connection getConnection() {
    try {
        Class.forName(driverName);
        try {
            con = DriverManager.getConnection(URL);
        } catch (SQLException ex) {
            System.out.println("Failed to create the database connection."); 
        }
    } catch (ClassNotFoundException ex) {
        // log an exception. for example:
        System.out.println("Driver not found."); 
    }
    return con;
}

}

2 个答案:

答案 0 :(得分:0)

会话和上下文

在Web应用程序中,您不应该考虑每个用户一个数据库连接。在Web应用程序中定义“用户”有点不确定。用户可能正在使用多个浏览器选项卡/窗口,甚至使用多个浏览器。用户可能正在启动和关闭会话,或者会话可能即将到期,并且用户重新连接。

相反,请考虑:

  • 会话
    每次用户在浏览器标签/窗口中访问您的Web应用程序时,都会启动一个会话。构建Java Servlet环境是为了代表您处理技术细节,并向您提供了HttpSession对象。当用户关闭浏览器选项卡/窗口时,或者在不活动超时之后,或者以编程方式关闭会话时,或者当Servlet容器确定诸如网络连接失败之类的问题时,会话都会关闭。
    • 每个会话都包含“属性”的键值存储,您可以在其中保留对象的作用域。
  • 上下文
    在运行时,“上下文”一词代表整个Web应用程序的Servlet。在处理第一个用户请求之前建立上下文,并在发送最后一个响应之后关闭上下文。
    • ServletContext对象上,您将找到与会话的属性存储类似的“属性”密钥存储。

Servlet规范定义了会话和上下文生命周期中的挂钩。

上下文生命周期的钩子是编写实现ServletContextListener的类。您实现了一对方法,一个方法由Servlet容器调用,然后处理第一个用户连接(您的Web应用程序正在启动),另一个方法在发出最后一个响应之后(您的Web应用程序正在关闭)被调用。在“堆栈溢出”中搜索有关该主题的大量现有文章。

DataSource

通常最好使用DataSource对象,而不是在那里显示连接。

JDBC driver中的jdbc.postgresql.org提供了DataSource的实现。有关详情,请参见此问题:Produce a DataSource object for Postgres JDBC, programmatically

使用DataSource接口的一个好处是,如果您更改为使用其他JDBC驱动程序(例如Postgres的pgjdbc-ng驱动程序),则无需更改对{ {1}}遍及整个代码库。

上面讨论的上下文启动挂钩是加载驱动程序,测试与数据库的连接以及配置getConnection对象的理想场所。将该DataSource对象存储在上述DataSource的“属性”键值存储中。

需要连接时,访问ServletContext对象以检索存储在其中的ServletContext作为属性。调用DataSource::getConnection为您的数据库获取一个Connection

完成操作后,请确保关闭DataSource对象。学习使用try-with-resources功能来使此琐事在您的代码中更加优雅和容易。

连接池

许多人会建议使用连接池。这里的理论是获得连接相对昂贵,需要大量时间和CPU周期。

没有缓冲,我们将获得与数据库的全新连接,进行一些有限的工作,然后关闭并丢弃该连接。 Connection对象超出范围,并成为垃圾收集的候选对象。在数据库方面,由Postgres Postmaster建立的用于处理该连接的进程已关闭,并且释放了内存。当请求新的连接时,邮政局长必须费心设置新进程并在主机操作系统中分配内存。

有了池,一堆现有的数据库连接保持打开状态,等待使用。当您的应用程序需要完成数据库工作时,会从池中检索连接,然后进行工作,然后当您认为要关闭连接时,该池实际上会进行干预以保持该连接的打开状态,以备将来使用。因此,与数据库的每次交互都不再意味着创建和销毁与数据库服务器的连接。

如果您走这条路,那么您在上面使用Connection所做的工作就会得到回报。您可以从将DataSource接口的全新连接每次实现与接口的连接池实现一起切换。因此,使用数据库的所有代码都无需更改。

我个人不再使用数据库连接池。我的实验表明,夸大昂贵连接的前提。另一个问题:您必须担心连接保持正确连接。例如,没有任何未决交易保持打开状态。另一个问题:尝试决定连接池的实现。这些年来已经有好几年了,所有的问题和问题都很多,从而启发了另一种实现方式。结果:在我看来,合并的风险收益率还不够好。

答案 1 :(得分:0)

您可以保持连接打开而不会关闭

使用连接池

(或)

或者您可以将连接对象保存在会话中,并在servlet中检索它,并在需要时将其传递给DAO类中的函数。