0

だから私は毎分データベースを照会するサーブレットを持っているので、1 つの接続だけを永久に開いていると思います (まあ、webapp が停止するまで)。したがって、init() で接続を開き、destroy() で閉じています。問題は、Tomcat でアプリを停止した後に DB を見ると、接続がまだ開いているということです。何が起こっていますか?

これが私のコードです:

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 メソッドにログインを追加しました。変。

では、サーブレットではない方法で記述してみましょう...

4

3 に答える 3

2

ドキュメントによるとdestroy()、サーブレット内のすべてのスレッドが終了するか、タイムアウトが発生した後にのみ呼び出されます。したがって、理論的には、コンテナーが正常に停止しない限り、常に destroy を呼び出す必要があります。

  1. コンテナーが正常に停止していることを確認します。
  2. destroy()メソッド内に例外はありません
  3. メソッドの開始時に何らかの文字列をログに記録するか、デバッガーでブレーク ポイントを設定してみてください。

また、古いバージョンの Tomcat を使用している場合は、このバグに注意してください。

于 2012-04-30T17:35:16.173 に答える
1

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"
        />

サーブレットでコンテキストを作成します

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
    }
  }
于 2012-04-30T17:59:12.070 に答える
0

init() および destroy() メソッドは、サーブレットのライフサイクルに関連付けられています。

一般的なサーブレットのライフサイクルは、コンテナー内のアプリケーションのライフ タイムです。

通常、汎用サーブレットの場合、アプリケーションはコンテナーにデプロイされ、アプリケーションが開始されます。この時点では、サーブレットは存在しません。

サーブレットにマップされた URL にリクエストが送信されると、コンテナはそのサーブレットのインスタンスがまだ開始されていないかどうかを確認します。そうでない場合は、サーブレットで init() メソッドを呼び出してから、サーブレットへのリクエストのルーティングを開始します。通常、一度にアプリケーション内に存在するサーブレットのインスタンスは 1 つだけです。

別の方法として、web.xml で load-on-startup パラメーターを使用してサーブレットを構成することができます。これが存在する場合、サーブレットは、サーブレットを初期化するための要求を待つのではなく、アプリケーションの起動時に初期化されます。

その後、コンテナーがシャットダウンされるか、アプリケーションがアンデプロイされると、コンテナーは、アプリケーションの存続期間中に初期化されたすべてのサーブレットで destroy() メソッドを呼び出します。

したがって、要約すると、init() および destroy() メソッドが個々のリクエストに結び付けられることを期待している場合、その期待は見当違いです。そのためには、ServletRequestListener (サーブレット 3.0)、またはサーブレット フィルター (3.0 以前) を使用したアドホックなものを調べます。

于 2012-04-30T17:27:03.667 に答える