一个通用的CloseableHttpClient工厂类

一个CloseableHttpClient工厂,基于java知名开源库apache-httpclient,能够忽略SSL,并且超时和状态异常时可以重试

<dependencies>

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.9</version>
    </dependency>

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.5.9</version>
    </dependency>

</dependencies>
package util;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.ConnectionClosedException;
import org.apache.http.HttpResponse;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.ServiceUnavailableRetryStrategy;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContextBuilder;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import java.net.SocketTimeoutException;


@Slf4j
public class HttpClientUtil {

    public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
            SSLContext sslContext = sslContextBuilder.loadTrustMaterial(null, (chain, authType) -> true).build();

            SSLConnectionSocketFactory ssl = new SSLConnectionSocketFactory(
                    sslContext,
                    new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"},
                    null,
                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);


            return HttpClients.custom()
                    .setSSLSocketFactory(ssl)
                    .setRetryHandler((e, executionCount, context) -> {
                        if (executionCount <= 20) {
                            if (e instanceof NoHttpResponseException
                                    || e instanceof ConnectTimeoutException
                                    || e instanceof SocketTimeoutException
                                    || e instanceof SSLHandshakeException) {
                                log.info("{} 异常, 重试 {}", e.getMessage(), executionCount);
                                return true;
                            }
                        }

                        return false;
                    })
                    .setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
                        @Override
                        public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) {
                            int statusCode = response.getStatusLine().getStatusCode();
                            if (statusCode != 200) {
                                if (executionCount <= 20) {
                                    log.info("{} 状态码异常, 重试 {}", statusCode, executionCount);
                                    return true;
                                }

                            }
                            return false;
                        }

                        @Override
                        public long getRetryInterval() {
                            return 0;
                        }
                    })
                    .build();
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

"如果文章对您有帮助,可以请作者喝杯咖啡吗?"

微信二维码

微信支付

支付宝二维码

支付宝


一个通用的CloseableHttpClient工厂类
https://blog.liuzijian.com/post/code-blocks/2023/01/01/java-httpclient.html
作者
Liu Zijian
发布于
2023年1月1日
许可协议