0

晚上好!我有一个带有登录-注销功能的网络应用程序,您可以在其中购买或出售一些产品。我的查询存储在一个名为 的 java 类中DBManager,它只有从 servlet 调用的静态方法(我不能使用 JSP,因为在这个项目中我们不能使用它们,教授给了我们这个约束)。

所以这就是问题所在:我曾经管理与ServletContextListener. 在contextInitialized我建立连接,并在contextDestroyed我关闭它。属性“Connection”使用ServletContext.setAttribute(Connection).

如何通过 java 类(不是 servlet)获取此参数DBManager?我必须getServletContext()在 servlet 中使用对象并将其作为属性传递,或者有避免这种情况的捷径?

4

3 回答 3

4

在 contextInitialized 方法中打开连接并在 contextDestroyed 中关闭它是一个糟糕的解决方案。想象一下,您的网站同时有两个访问者。他们现在将共享相同的数据库连接。如果您使用事务,您最终会得到意想不到的结果,其中一个访问者提交了另一个访问者执行的事务的中间状态。如果连接丢失(可能是因为数据库服务器重新启动),您的应用程序将失败,因为它没有重新建立连接(除非您有一个非常智能的 JDBC 驱动程序)。

一个非常昂贵但安全的解决方案是为每个数据库操作打开一个新连接,并在操作后立即再次关闭它。

对于完美的解决方案,您将使用某种连接池。每当您需要执行数据库语句(或一系列语句)时,您都会从池中借用一个连接。完成后,您会将连接返回到池。大多数池实现会处理诸如验证之类的事情(检查连接是否仍然“活动”),并且多个线程(不同访问者同时发送不同的 HTTP 请求)可以并行执行语句。

如果您想采用此解决方案,也许 Commons DbUtils 库适合您:http ://commons.apache.org/dbutils/

或者,您可以查看 Java 应用程序服务器或 servlet 引擎(Tomcat?)的文档,了解它提供了哪些内置的 DB 连接池功能。

于 2012-11-21T19:55:45.640 回答
1

您可以更改您的类以接收连接,而不是任意获取连接。这允许您传递任何连接实例(如果您需要从另一个数据库获取数据会发生什么?)。

另外,假设代码将被移植到桌面。使用这种方法,您可以重用您的DAO,而无需进行任何更改。

class DBManager {
  private Connection connection;

  public DBManager(Connection connection) {
    this.connection = connection;
  }
  //methods that will use the connection
}
于 2012-11-21T19:51:39.007 回答
0

在您的HttpServlet doPostordoGet方法中,您可以调用getServletContext().

ServletContext sc = getServletContext();
DataSource ds = (DataSource) sc.getAttribute("ds");
Connection conn = ds.getConnection();

servlet 可以通过名称将对象属性绑定到上下文中。绑定到上下文中的任何属性都可用于属于同一 Web 应用程序的任何其他 servlet。

上下文属性对于创建它们的 JVM 来说是本地的。这可以防止 ServletContext 属性成为分布式容器中的共享内存存储。当需要在分布式环境中运行的 servlet 之间共享信息时,应将信息放入会话中、存储在数据库中或设置在 Enterprise JavaBeans 组件中。

于 2012-11-21T19:52:36.050 回答