2

現在、Jersey/Tomcat を使用して REST Web サービスを開発しています (ただし、一般的なサーブレット/コンテナーの回答は大歓迎です)。クライアントが、MySQL 接続から大量のデータを返すサービスで GET リクエストを行う場合。

OOM 例外を回避するために、MySQL のストリーミング モードを使用します。

ただし、ロード中にクライアントがリクエストを中止した場合、MySQL 接続は閉じられません。一度に 1 つの「ストリーミング」リクエストしか実行できないため、その後、サーバーは他のリクエストを処理しません。

問題は、サーバーでリクエストが終了するたびに (通常または異常に) 通知を受け取るにはどうすればよいかということです。ある種のリスナーを登録できますか? または UncaughtExceptionHandler を使用しますか?

ジャージーで例外を処理して「応答」に変換することについて多くのことを見てきましたが、リクエストの途中での終了を処理するものは何もありません。Jersey または Tomcat は、通知なしにスレッドを単純に破棄する可能性があると思います。メソッドの重要な部分で例外をキャッチして、そのようなスレッドの中断がいつ発生したかを知ることはできますか?

よろしくお願いいたします。

ラファエル

4

1 に答える 1

2

通常、反対側が接続を中止している間に、またはが呼び出されるIOExceptionたびに がスローされます。flush()close()response.getOutputStream()

通常、DB 接続 (およびその他のリソース) のクローズは、例外が発生した場合でもクローズされるように、それがオープンされたfinallyブロックのブロックで発生する必要があります。try

要約すると、この例は次のようにする必要があります。

String search = getItSomehow();
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;

try {
    connection = database.getConnection();
    statement = connection.prepareStatement(SQL_FIND);
    statement.setString(1, search);
    resultSet = statement.executeQuery();

    if (resultSet.next()) {
        response.setContentType(resultSet.getString("contentType"));
        response.setContentLength(resultSet.getInt("contentLength")); // Optional.
        BufferedInputStream input = null;
        BufferedOutputStream output = null;
        try {
            input = new BufferedInputStream(resultSet.getBinaryStream("content"));
            output = new BufferedOutputStream(response.getOutputStream());
            byte[] buffer = new byte[1024];
            for (int length; (length = input.read(buffer)) > 0;) {
                output.write(buffer, 0, length);
                output.flush();
            }
        } finally {
            if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
            if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
        }
    } else {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
    }
} catch (SQLException e) {
    throw new ServletException("Something failed at SQL/DB level.", e);
} finally {
    if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
    if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
    if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
于 2010-06-09T14:44:21.170 に答える