使用Apache HttpClient 4.x進行異常重試

來源:互聯網
上載者:User

標籤:text   finally   prot   body   tom   socket   lang   span   context   

在進行http請求時,難免會遇到請求失敗的情況,失敗後需要重新請求,嘗試再次擷取資料。

Apache的HttpClient提供了異常重試機制,在該機制中,我們可以很靈活的定義在哪些異常情況下進行重試。

重試前提

被請求的方法必須是等冪的:就是多次請求服務端結果應該是準確且一致的。 

適合的方法:比如根據ID,修改人員姓名,無論請求多次結果都是一樣,這就是等冪。 不適合的方法:比如減少帳號50元,多次請求將多次扣減。實現方式想要實現異常重試,需要實現它提供的一個介面  HttpRequestRetryHandler ,並實現 retryRequest 方法。然後set到HttpClient中。該httpClient就具備了重試機制。 HttpClient自身提供了 StandardHttpRequestRetryHandler 和 DefaultHttpRequestRetryHandler 兩個實作類別。 DefaultHttpRequestRetryHandler 繼承自 DefaultHttpRequestRetryHandler , StandardHttpRequestRetryHandler 預設幾個方法為等冪,如PUT、GET、HEAD等除POST外的方法,如果自訂可以參考它的實現方式。 代碼如下:
  1 import java.io.IOException;  2 import java.io.InterruptedIOException;  3 import java.net.ConnectException;  4 import java.net.UnknownHostException;  5   6 import javax.net.ssl.SSLException;  7   8 import org.apache.commons.lang3.ObjectUtils;  9 import org.apache.commons.lang3.StringUtils; 10 import org.apache.http.Consts; 11 import org.apache.http.HttpEntityEnclosingRequest; 12 import org.apache.http.HttpRequest; 13 import org.apache.http.HttpStatus; 14 import org.apache.http.ParseException; 15 import org.apache.http.client.HttpRequestRetryHandler; 16 import org.apache.http.client.config.RequestConfig; 17 import org.apache.http.client.methods.CloseableHttpResponse; 18 import org.apache.http.client.methods.HttpPost; 19 import org.apache.http.client.protocol.HttpClientContext; 20 import org.apache.http.entity.ContentType; 21 import org.apache.http.entity.StringEntity; 22 import org.apache.http.impl.client.CloseableHttpClient; 23 import org.apache.http.impl.client.HttpClients; 24 import org.apache.http.protocol.HttpContext; 25 import org.apache.http.util.EntityUtils; 26  27 /** 28  * @author 29  * 29  * @date 2017年5月18日 上午9:17:30 30  * 31  * @Description 32  */ 33 public class HttpPostUtils { 34     /** 35      *  36      * @param uri 37      *            the request address 38      * @param json 39      *            the request data that must be a JSON string 40      * @param retryCount 41      *            the number of times this method has been unsuccessfully 42      *            executed 43      * @param connectTimeout 44      *            the timeout in milliseconds until a connection is established 45      * @param connectionRequestTimeout 46      *            the timeout in milliseconds used when requesting a connection 47      *            from the connection manager 48      * @param socketTimeout 49      *            the socket timeout in milliseconds, which is the timeout for 50      *            waiting for data or, put differently, a maximum period 51      *            inactivity between two consecutive data packets 52      * @return null when method parameter is null, "", " " 53      * @throws IOException 54      *             if HTTP connection can not opened or closed successfully 55      * @throws ParseException 56      *             if response data can not be parsed successfully 57      */ 58     public String retryPostJson(String uri, String json, int retryCount, int connectTimeout, 59             int connectionRequestTimeout, int socketTimeout) throws IOException, ParseException { 60         if (StringUtils.isAnyBlank(uri, json)) { 61             return null; 62         } 63  64         HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() { 65  66             @Override 67             public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { 68                 if (executionCount > retryCount) { 69                     // Do not retry if over max retry count 70                     return false; 71                 } 72                 if (exception instanceof InterruptedIOException) { 73                     // An input or output transfer has been terminated 74                     return false; 75                 } 76                 if (exception instanceof UnknownHostException) { 77                     // Unknown host 修改代碼讓不識別主機時重試,實際業務當不識別的時候不應該重試,再次為了示範重試過程,執行會顯示retryCount次下面的輸出 78                     System.out.println("不識別主機重試"); return true; 79                 } 80                 if (exception instanceof ConnectException) { 81                     // Connection refused 82                     return false; 83                 } 84                 if (exception instanceof SSLException) { 85                     // SSL handshake exception 86                     return false; 87                 } 88                 HttpClientContext clientContext = HttpClientContext.adapt(context); 89                 HttpRequest request = clientContext.getRequest(); 90                 boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); 91                 if (idempotent) { 92                     // Retry if the request is considered idempotent 93                     return true; 94                 } 95                 return false; 96             } 97         }; 98  99         CloseableHttpClient client = HttpClients.custom().setRetryHandler(httpRequestRetryHandler).build();100         HttpPost post = new HttpPost(uri);101         // Create request data102         StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);103         // Set request body104         post.setEntity(entity);105 106         RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout)107                 .setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout).build();108         post.setConfig(config);109         // Response content110         String responseContent = null;111         CloseableHttpResponse response = null;112         try {113             response = client.execute(post, HttpClientContext.create());114             if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {115                 responseContent = EntityUtils.toString(response.getEntity(), Consts.UTF_8.name());116             }117         } finally {118             if (ObjectUtils.anyNotNull(response)) {119                 response.close();120             }121             if (ObjectUtils.anyNotNull(client)) {122                 client.close();123             }124         }125         return responseContent;126     }

 

轉載自:http://www.cnblogs.com/wuxiaofeng/p/6879292.html,感謝分享。

使用Apache HttpClient 4.x進行異常重試

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.