2010-06-09 72 views
2

我目前正在使用Jersey/Tomcat開發一個REST Web服務(但歡迎使用通用的Servlet/Container答案)。 如果客戶端對從MySQL連接返回大量數據的服務執行一些GET請求。處理servlet中意外的請求結束

爲了避免任何OOM異常,我使用MySQL的流模式。

但是,如果客戶端在加載期間中止請求,那麼MySQL連接未關閉。 之後,服務器將不會處理任何其他請求,因爲一次只能有一個「流式傳輸」請求。

所以問題是:我的服務器上的請求何時結束(通常或異常),我該如何得到通知。我可以註冊某種聽衆嗎?或者使用UncaughtExceptionHandler?

我已經看到很多關於處理Jersey中的異常以將它們轉換爲「響應」的事情,但沒有處理請求的過早結束。我猜Jersey或Tomcat可能會在不通知的情況下摧毀我的線程。我可以在我的方法的關鍵部分捕獲一些異常,以便在線程中斷髮生時知道嗎?

預先感謝您的幫助,

拉斐爾

回答

2

通常,每當flush()close()已呼籲response.getOutputStream(),而對方已經中止連接的IOException將被拋出。

通常情況下,關閉數據庫連接(和其他資源)應發生在try塊的finally塊中,因爲它已被打開,所以在異常情況下它將被關閉。

總結,這個例子應該做的:

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) {} 
} 
+0

沒有必要關閉輸出流 - servlet將爲你做它。另外,如果您使用PrintWriter,則使用checkError而不是flush。 – 2013-09-06 10:31:30

+0

@andrew:http://stackoverflow.com/questions/1829784/should-i-close-the-servlet-outputstream/1829823#1829823 – BalusC 2013-09-06 11:02:35