HttpClient 连接超时重试处理

记录一次HttpClient 连接超时重试问题

原代码如下:

public static void main(String[] args) throws UnsupportedEncodingException {

		HttpClient httpClient = new HttpClient();
    	httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
        String url="XXXXXX你的请求接口";
        GetMethod getMethod = new GetMethod(url);
        //设置请求超时为5秒
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);
        //设置请求重试处理,用的是默认的重试处理:请求三次
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
        String response = "";
        
        try {
        	int statusCode = httpClient.executeMethod(getMethod);
        	if (statusCode != HttpStatus.SC_OK){
                System.err.println("请求出错:" + getMethod.getStatusLine());
            }
        	byte[] responseBody = getMethod.getResponseBody();
            response = new String(responseBody, "utf-8");
            System.out.println("-----------response:" + response);
            
        } catch (HttpException e) {
        	System.out.println("请检查输入的URL!");
            e.printStackTrace();
        } catch (IOException e) {
        	System.out.println("发生网络异常!");
        } finally {
        	getMethod.releaseConnection();
        }

	}

getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());  =====》这里设置了默认的请求重试处理类,默认会重试3次。

实测过程中发现在连接超时后直接报错SocketTimeoutException,并不会重试。

为什么呢?这里我们看下DefaultHttpMethodRetryHandler、SocketTimeoutException这两个类的源码。

1、发现SocketTimeoutException继承InterruptedIOException

 

2、在DefaultHttpMethodRetryHandler请求处理中retryMethod这个方法会判断是否进行重试,第109行发现在判断异常类型为InterruptedIOException时,返回false

 真相大白,在httpclient的默认重试处理类(DefaultHttpMethodRetryHandler)中,连接超时报错会并不会重试。

这里我们可以自定义重试处理类(复制粘贴DefaultHttpMethodRetryHandler的类,将这里return true,或者直接在上面加一个判断SocketTimeoutException

异常的代码)就可以了,然后将这里换成我们自己的处理类。

 

自定义处理类代码如下MyHttpMethodRetryHandler:


import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpMethodRetryHandler;
import org.apache.commons.httpclient.NoHttpResponseException;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.NoRouteToHostException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

public class MyHttpMethodRetryHandler implements HttpMethodRetryHandler {

    private static Class SSL_HANDSHAKE_EXCEPTION = null;

    static {
        try {
            SSL_HANDSHAKE_EXCEPTION = Class.forName("javax.net.ssl.SSLHandshakeException");
        } catch (ClassNotFoundException ignore) {
        }
    }
    /** the number of times a method will be retried */
    private int retryCount;

    /** Whether or not methods that have successfully sent their request will be retried */
    private boolean requestSentRetryEnabled;

    /**
     * Creates a new DefaultHttpMethodRetryHandler.
     * @param retryCount the number of times a method will be retried
     * @param requestSentRetryEnabled if true, methods that have successfully sent their request will be retried
     */
    public MyHttpMethodRetryHandler(int retryCount, boolean requestSentRetryEnabled) {
        super();
        this.retryCount = retryCount;
        this.requestSentRetryEnabled = requestSentRetryEnabled;
    }

    /**
     * Creates a new DefaultHttpMethodRetryHandler that retries up to 3 times
     * but does not retry methods that have successfully sent their requests.
     */
    public MyHttpMethodRetryHandler() {
        this(3, false);
    }
    /**
     * Used <code>retryCount</code> and <code>requestSentRetryEnabled</code> to determine
     * if the given method should be retried.
     *
     * @see HttpMethodRetryHandler#retryMethod(HttpMethod, IOException, int)
     */
    @Override
    public boolean retryMethod(
            final HttpMethod method,
            final IOException exception,
            int executionCount) {
        if (method == null) {
            throw new IllegalArgumentException("HTTP method may not be null");
        }
        if (exception == null) {
            throw new IllegalArgumentException("Exception parameter may not be null");
        }
        // HttpMethod interface is the WORST thing ever done to HttpClient
        if (method instanceof HttpMethodBase) {
            if (((HttpMethodBase)method).isAborted()) {
                return false;
            }
        }
        if (executionCount > this.retryCount) {
            // Do not retry if over max retry count
            return false;
        }
        if (exception instanceof NoHttpResponseException) {
            // Retry if the server dropped connection on us
            return true;
        }
        if (exception instanceof SocketTimeoutException) {
            return true;
        }
        if (exception instanceof InterruptedIOException) {
            // Timeout
            return false;
        }
        if (exception instanceof UnknownHostException) {
            // Unknown host
            return false;
        }
        if (exception instanceof NoRouteToHostException) {
            // Host unreachable
            return false;
        }
        if (SSL_HANDSHAKE_EXCEPTION != null && SSL_HANDSHAKE_EXCEPTION.isInstance(exception)) {
            // SSL handshake exception
            return false;
        }
        if (!method.isRequestSent() || this.requestSentRetryEnabled) {
            // Retry if the request has not been sent fully or
            // if it's OK to retry methods that have been sent
            return true;
        }
        // otherwise do not retry
        return false;
    }

    /**
     * @return <code>true</code> if this handler will retry methods that have
     * successfully sent their request, <code>false</code> otherwise
     */
    public boolean isRequestSentRetryEnabled() {
        return requestSentRetryEnabled;
    }

    /**
     * @return the maximum number of times a method will be retried
     */
    public int getRetryCount() {
        return retryCount;
    }
}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值