簡體   English   中英

Servlet的destroy方法並沒有關閉數據庫連接,即使我也告訴過它

[英]Servlet's destroy method isn't closing the DB connection even thought I told it too

所以我有一個每分鍾查詢數據庫的servlet,所以我想我將永遠打開一個連接(好吧,直到webapp停止)。 因此我在init()中打開一個連接並在destroy()中關閉它。 事實是,如果我在tomcat中停止應用程序后查看數據庫,則連接仍處於打開狀態。 發生了什么?

這是我的代碼:

public void init() throws ServletException
{
    try
    {
        // Prepare the DB connection
        DriverManager.registerDriver(new com.informix.jdbc.IfxDriver());
        informixConnection = DriverManager.getConnection(DBURL, DBUsername, DBPassword);
    }
    catch(SQLException e)
    {
        throw new UnavailableException("Error connecting to the database");
    }
}

public void destroy()
{
    try
    {
        informixConnection.close();     
    }
    catch(Exception e)
    {
    }
}

還有一個方法實際上是一個查詢,一個doGet,所以用戶可以得到最新的響應,但我還沒有完成那些(雖然我已經測試了它們,數據庫連接工作)。


我不知道為什么這不起作用。 我在destroy方法中添加了一些日志記錄,以確認在應用程序關閉時它被調用,突然它開始工作了。 奇怪的。

好的,現在去以非servlet方式編寫它...

根據文檔,只有在servlet中的所有線程都退出或發生超時后才會調用destroy() 所以理論上應該始終調用destroy,除非容器沒有優雅地停止。

  1. 驗證容器是否正常停止。
  2. destroy()方法中沒有例外
  3. 嘗試在方法的乞討時記錄一些字符串或在調試器中設置斷點。

此外,如果您使用舊版本的Tomcat,請注意此錯誤

init()和destroy()方法與Servlet的生命周期相關聯。

典型servlet的生命周期是容器中應用程序的生命周期。

在正常情況下,對於通用servlet,將應用程序部署到容器,並啟動應用程序。 此時,servlet不存在。

一旦請求被定向到映射到Servlet的URL,容器將檢查它是否還沒有啟動該Servlet的實例。 如果沒有,它將調用Servlet上的init()方法,然后開始向它發送路由請求。 通常,應用程序中一次只有一個Servlet實例。

作為替代方案,可以在web.xml中使用load-on-startup參數配置Servlet,如果存在,則在應用程序啟動期間初始化Servlet,而不是等待初始化Servlet的請求。

稍后,當容器關閉或應用程序取消部署時,容器將在應用程序生命周期內初始化的任何Servlet上調用destroy()方法。

因此,總而言之,如果您希望init()和destroy()方法與各個請求相關聯,那么您的期望就會錯位。 為此,你會看到一個ServletRequestListener(Servlet 3.0),或使用Servlet過濾器(3.0之前的版本)。

如果您正在使用Tomcat,則可以創建資源

  <Resource name="jdbc/AutoOracle"
        auth="Container"
        type="javax.sql.DataSource"
        driverClassName="oracle.jdbc.driver.OracleDriver"
        username="usrname"
        password="pswd"
        url="jdbc:oracle:thin:@yourdb:1521:yourdb"
        maxActive="1500"
        maxIdle="30"
        maxWait="5000"
        removeAbandoned="true"
        removeAbandonedTimeout="900"
        timeBetweenEvictionRunsMillis="300000"
        minEvictableIdleTimeMillis="1800000"
        testOnBorrow="true"
        testWhileIdle="true"
        validationQuery="select 'test' from Dual"
        validationQueryTimeout="3"
        />

在您的servlet中創建一個Context

Context dataSourceContext = new InitialContext();

然后使用上下文在需要連接的方法內創建數據庫連接。

  Connection conn = null;
  try{
    DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/AutoOracle");
    conn = ds.getConnection();
    if(conn == null){
      log.error("Connection is null");
    }else{
      // do some work
    }
  }catch(Exception e){
    // handle exceptions
  }finally{
    try{
      conn.close();
    }catch(Exception e){
      // handle exception
    }
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM