中restTemplate超时、连接池、相应错误码处理配置

时间:2025-02-24 21:26:23

1、restTemplate超时配置

通过定义ClientHttpRequestFactory工厂并配置超时时间初始化restTemplate。RestTemplate默认也是用的ClientHttpRequestFactory的。

public RestTemplate iRestTemplate() {
        SimpleClientHttpRequestFactory httpClientFactory= new SimpleClientHttpRequestFactory();
        (2000);
        (10000);
        return new RestTemplate(httpClientFactory);
    }

2、支持连接池配置

默认的ClientHttpRequestFactory使用的是HttpUrlConnection,本身不支持连接池。当需要启用连接池提高吞吐量或者减少请求响应时间,替换掉默认的ClientHttpRequestFactory,如Apache HttpComponents HttpClient。


@Bean
public RestTemplate restTemplate(@Qualifier("clientHttpRequestFactory") ClientHttpRequestFactory factory) {
        RestTemplate restTemplate = new RestTemplate(factory);
        ().set(1,
                new StringHttpMessageConverter(("UTF-8")));
        return restTemplate;
    }

@Bean(name = "clientHttpRequestFactory")
    public ClientHttpRequestFactory clientHttpRequestFactory(HttpClient client) {

        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new
                HttpComponentsClientHttpRequestFactory(client);
        (());
        (());
        (());
        return clientHttpRequestFactory;
    }

    @Bean
    public HttpClient httpClient() {
        HttpClientBuilder httpClientBuilder = ();
        try {
            // 针对https协议相关配置
            SSLContext sslContext = ("SSL");// 获取一个SSLContext实例
            TrustManager[] trustAllCerts = {new InsecureTrustManager()};
            (null, trustAllCerts, new ());// 初始化SSLContext实例

            //设置信任ssl访问
            (sslContext);
            HostnameVerifier hostnameVerifier = ;
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    // 注册http和https请求
                    .register("http", ())
                    .register("https", sslConnectionSocketFactory).build();
            PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            (());
            (());
            (poolingHttpClientConnectionManager);
            (new DefaultHttpRequestRetryHandler((), true));

            //设置默认请求头
            List<Header> headers = getDefaultHeaders();
            (headers);

            ();
            ((), );
            CloseableHttpClient httpClient = ();
            ().addShutdownHook(new Thread(() -> {
                try {
                    ();
                } catch (IOException e) {
                    ("close http client error.", e);
                }
            }));
            return httpClient;
        } catch (Exception e) {
            ("HttpClient create error.", e);
        }
        return null;
    }

    private List<Header> getDefaultHeaders() {
        List<Header> headers = new ArrayList<>();
        (new BasicHeader("Connection", "Keep-Alive"));
        return headers;
    }

    class InsecureTrustManager implements X509TrustManager {

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}

        /**
         * 返回受信任的X509证书数组
         */
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

    }
public class HttpClientProperties {
 
    private int readTimeout;
 
    private int connectTimeout;
 
    private int acquireConnectionTimeout;
 
    private int maxConnection;
 
    private int maxConnectionRoute;
 
    private int retryTimes;
 
    private int idleTime;
}

3、响应状态错误码处理

默认实现,如果是4xx或者5xx,请求响应的时候会抛出异常:

/**
 * #handleError()
 */
protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException {
		String statusText = ();
		HttpHeaders headers = ();
		byte[] body = getResponseBody(response);
		Charset charset = getCharset(response);
		String message = getErrorMessage((), statusText, body, charset);

		switch (()) {
			case CLIENT_ERROR:
				throw (message, statusCode, statusText, headers, body, charset);
			case SERVER_ERROR:
				throw (message, statusCode, statusText, headers, body, charset);
			default:
				throw new UnknownHttpStatusCodeException(message, (), statusText, headers, body, charset);
		}
	}

在一些场景中,某些接口可能会通过不同的状态码来返回不同的错误信息,不是返回200的状态码,在消息体使用code等字段来标识,如果是4xx或者5xx的时候不希望抛异常,而由我们自己获取判断处理,可以如下方式定义:

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        ().set(1,
                new StringHttpMessageConverter(("UTF-8")));
        (new ResponseErrorHandler() {
            @Override
            public boolean hasError(ClientHttpResponse response) throws IOException {
                return false;
            }
 
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
 
            }
        });
        return restTemplate;
    }