2016-03-12 23 views
1

我有以下方法,它使用Apache Commons Http客戶端向給定URI發送異步GET並返回Future與響應。從嘗試資源結構返回未來

CloseableHttpAsyncClient實現Closeable因此我使用try/resource結構。

public static Future<HttpResponse> sendAsyncGet(String uri) throws IOException { 
    try (CloseableHttpAsyncClient asyncHttpClient = HttpAsyncClients.createDefault()) { 
     asyncHttpClient.start(); 
     HttpGet httpGet = new HttpGet(uri); 
     return asyncHttpClient.execute(httpGet, null); 
    } 

下面你可以看到這種用法:

Future<HttpResponse> future = sendAsyncGet("http://www.apache.org"); 
future.get(3, TimeUnit.SECONDS); 

的問題是,當我叫得到一個未來它不會返回所需的HttpResponse。如果我使用重載的get()方法,它會一直等到超時或永遠超時。我想這是因爲嘗試/資源沒有正確釋放。

我該如何改進給定的方法/代碼才能正確使用:未來包含在方法體中的try /資源結構?

更新:

這是Maven的依賴:

<dependency> 
     <groupId>org.apache.httpcomponents</groupId> 
     <artifactId>httpasyncclient</artifactId> 
     <version>4.1.1</version> 
     <scope>test</scope> 
    </dependency> 
+0

「問題是,當我打電話給未來它不會返回所需的HttpResponse。如果我使用重載的get()方法,它會一直等到超時或永遠超時。​​「是的,這就是Future應該如何工作的。如果你不想讓它等待,你爲什麼要讓它等待三秒? – VGR

+2

離開try/resource-block會在打開的asyncHttpClient上調用close()。我假設關閉的httpClient在未來的等待中沒有調用complete或completeExceptionally。請查閱使用過的庫的文檔! – Heri

+0

@VGR:當我修改方法(例如,將其簽名更改爲void)並處理try/resource語句中的futureResponse時,我可以在將來運行get()並獲得結果。 問題是我不知道如何從該方法返回'future',並確保在方法外調用get()之後資源會關閉。 這可能嗎?我想不是,如果不是,那麼我怎樣才能以其他方式解決問題?我只想將URI傳遞給方法和強制方法,爲我完成所有骯髒的工作,並在完成後關閉連接。 – Robert

回答

1

嘗試使用資源已接收到響應之前將關閉異步客戶端。

您可能想要關閉異步客戶端,以避免將來傳遞給執行調用的回調。

public static Future<HttpResponse> sendAsyncGet(String uri) throws IOException { 
    final CloseableHttpAsyncClient asyncHttpClient; 

    asyncHttpClient = HttpAsyncClients.createDefault(); 
    asyncHttpClient.start(); 

    return asyncHttpClient.execute(new HttpGet(uri), new FutureCallback<HttpResponse>() { 
     private void close() { 
      try { 
       asyncHttpClient.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

     @Override 
     public void completed(HttpResponse response) { 
      close(); 
      System.out.println("completed"); 
     } 

     @Override 
     public void failed(Exception e) { 
      close(); 
      e.printStackTrace(); 
     } 

     @Override 
     public void cancelled() { 
      close(); 
      System.out.println("cancelled"); 
     } 
    }); 
}