【问题标题】:How to create one database connection per user on a Java Servlet application?如何在 Java Servlet 应用程序上为每个用户创建一个数据库连接?
【发布时间】:2011-07-24 00:10:42
【问题描述】:

我正在使用 Java Servlets 开发一个网站,我的研究表明,最好为每个用户保留一个数据库连接(而不是始终只有一个连接位于后台或每次都连接到数据库)需要进行交易)。但是,我不知道如何做到这一点。我目前正在做的是在我的数据访问对象类中我有一个

private static Connection conn;

我有一个HTTPSessionListener - 在sessionCreated 事件上我使用这个静态“conn”变量连接到数据库,在sessionDestroyed 事件上我断开“conn”变量:

...在我的“MySessionListener”...

public void sessionCreated(HttpSessionEvent sessionEvent) {
    System.out.println("Session created!");
    DAO.connect();

}

public void sessionDestroyed(HttpSessionEvent sessionEvent) 
{
    System.out.println("Session destroyed");
    String user = (String) sessionEvent.getSession().getAttribute("userid" );
    if (user != null) DAO.signUserOut(user);
    DAO.disconnect();
}

现在的问题是:

  1. 恐怕这样我基本上会降级为只有一个每个人都共享的连接(而不是我想要的每个用户的连接),只是如果没有用户我会不时断开连接。正确吗?
  2. 如果多个用户在线并且一个人关闭了他们的会话,他们将关闭每个人的连接,直到其他人启动会话并为每个人创建一个新连接,对吗?我无法很好地对此进行测试,因为我在笔记本电脑上使用 3 个浏览器进行本地测试,但即使我关闭了打开我的网站的浏览器,会话也不会立即终止,我不确定到底发生了什么.我所知道的是,有时我会收到一个异常提示“连接关闭后不允许交易”。

【问题讨论】:

    标签: java mysql servlets connection-pooling


    【解决方案1】:

    通常这是使用连接池来实现的。您可以将其配置为具有特定数量的可用连接,并且池管理打开和关闭的连接。您的代码只会从池中获取可用连接并在完成后返回它。

    看到这个(相当通用)Wikipedia article

    一些著名的池是DBCPC3P0

    【讨论】:

    • 警告:虽然链接的 Oracle 文章给出了关于连接池基本工作原理的正确基本概念,但提供的用作启动示例的代码示例不应用于生产!它非常有问题且不可扩展。而是使用 servletcontainer 提供的连接池设施。甚至 Tomcat 都内置了连接池。
    • @BalusC 你是对的,这可能有点令人困惑,所以我现在删除了这些引用。
    • 谢谢你们,我现在正在看people.apache.org/~fhanik/jdbc-pool/jdbc-pool.html,并且会弄清楚如何使用Tomcat的连接池。会问我是否还有其他问题。谢谢!
    【解决方案2】:

    这里有两个问题:

    • http 会话超时
    • 数据库会话连接

    您似乎混淆了这两个会话概念。

    HTTP 会话

    您需要进一步熟悉客户端-服务器 http 机制。关闭浏览器不会关闭 http 会话。当您关闭浏览器时,您必须在“关闭时”将代码写入您的页面。 “关闭”??绝对不是——在 html/javascript 中没有 onclose 之类的东西。但是有onunload(以及onload)。

    为什么 javascript/html 中没有“onclose”?我认为发明 http/html 的人对许多意外情况都偏执。也许,没错。或许,我们必须了解 html/http 发明的心态和动机。因此,您别无选择,只能炮制 onunload 事件的连锁反应。 ONUNLOAD/ONLOAD 是 html 页面事件,而不是浏览器事件。整个 html 机制是页面驱动的,而不是浏览器驱动的。因此,当您关闭浏览器时,会触发浏览器上每个标签页的 onunload 事件。

    您必须使用页面 onunload 来通知服务器用户打算关闭会话。否则,服务器将不得不依赖会话超时值来结束会话。如果用户在您没有在 onunload 事件中编码的页面上关闭浏览器怎么办?太糟糕了——这就是为什么我在每一页上都写了“炮制 onunload 的连锁反应”。这是非常令人厌烦和烦人的。

    有时。特别是对于高度数学化的 servlet,服务器需要很长时间才能响应。然后客户端页面需要一个指示来区分仍在处理响应的服务器与服务器已经死机 - 在浏览器上强制执行会话超时。例如http://support.microsoft.com/kb/813827(如何更改 Internet Explorer 中的默认保活超时值)。

    可能是,服务器应该偶尔戳一下浏览器页面,看看浏览器会话是否仍然存在。没有。 Http 是客户端拉取技术。服务器无法将响应推送到客户端。为什么不?为什么这么傻?您必须阅读整个 http/html 心态/偏执狂才能理解。浏览器可以戳服务器,但反之则不行。

    因此,发明/制造了 AJAX 和彗星。模拟,假装服务器推送。使用 ajax,您可以通过某种方式让服务器对客户端进行伪戳。这就是你必须做的——使用 ajax,例如jquery 或 gwt。我更喜欢gwt。

    如果客户端计算机出现电源故障或操作系统蓝屏,或浏览器进程突然终止怎么办?没有机会触发任何页面的 onunload 事件。

    数据库连接会话

    Alex 的回答一针见血——连接池。但是,在某些情况下,我需要每个会话都有一个数据库连接。嗯......我该怎么做?是的,我将连接存储为会话属性。因此,数据库连接数与会话数一样多。这基本上与您当前正在执行的操作具有相同的效果。

    为无状态(尽管有 cookie)和假定的不稳定客户端开发有状态 Web 应用程序需要谨慎。如果用户在注销后按下返回按钮怎么办? backed/prev 页面可能包含导致服务器使用数据库连接的操作,该连接在用户按下后退按钮之前已被注销页面关闭。或者,可能是由于客户端没有在服务器上戳的时间超过会话保持活动超时值,导致服务器超时。

    因此,在开发“多层”客户端-服务器应用程序之前,您必须坐下来规划所有可能发生的情况,并充分了解 http 技术的思维模式/偏执狂。为了设计您的应用程序,您需要感染 http 的强迫症。

    【讨论】:

    • 谢谢。在你回答的第一部分 - 关于 HTTP 会话 - 我几乎可以肯定会话在浏览器关闭后会超时.. 但你提醒我一个很好的观点 - 服务器无法戳客户端.. 这意味着我不得不担心会话仍然打开时会随机死亡。你是否建议我服务的每个页面都有一些 ajax 函数,它会定期戳服务器,基本上什么都不做,只是为了戳?
    • "你是否建议每个页面......都有一些周期性戳服务器的 ajax 函数......?"阅读彗星和长轮询。
    猜你喜欢
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    • 2012-04-09
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    相关资源
    最近更新 更多