RestTemplate实践 (6)

HttpComponentsClientHttpRequestFactory底层使用Apache HttpClient创建请求,访问远程的Http服务,可以使用一个已经配置好的HttpClient实例创建HttpComponentsClientHttpRequestFactory请求工厂,HttpClient实例中可以配置连接池和证书等信息

添加HttpClient依赖 <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>x.x.x</version> <!-- springboot项目不用指定 --> </dependency> 设置超时时间

设置超时时间,可以直接使用Spring的底层基于HttpClient的HttpComponentsClientHttpRequestFactory,此处设置的是ClientHttpRequestFactory级别的全局超时时间

@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(clientHttpRequestFactory()); } @Bean private ClientHttpRequestFactory clientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); factory.setConnectTimeout(30 * 1000); //连接超时时间 factory.setReadTimeout(60 * 1000); //读超时时间 return factory; } }

注意:如果通过一个HttpClient实例创建HttpComponentsClientHttpRequestFactory,并通过HttpClient指定了DefaultRequestConfig,设置了connectTimeout、readTimeout等,在实际执行请求创建request时会与HttpComponentsClientHttpRequestFactory的配置合并,connectTimeout、socketTimeout、connectionRequestTimeout 以HttpComponentsClientHttpRequestFactory的配置为准

HttpComponentsClientHttpRequestFactory: /** * Merge the given {@link HttpClient}-level {@link RequestConfig} with * the factory-level {@link RequestConfig}, if necessary. * @param clientConfig the config held by the current httpClient级别的requestConfig配置 * @return the merged request config * (may be {@code null} if the given client config is {@code null}) * @since 4.2 */ protected RequestConfig mergeRequestConfig(RequestConfig clientConfig) { if (this.requestConfig == null) { // nothing to merge return clientConfig; } RequestConfig.Builder builder = RequestConfig.copy(clientConfig); int connectTimeout = this.requestConfig.getConnectTimeout(); //HttpComponentsClientHttpRequestFactory级别的配置 if (connectTimeout >= 0) { builder.setConnectTimeout(connectTimeout); } int connectionRequestTimeout = this.requestConfig.getConnectionRequestTimeout(); if (connectionRequestTimeout >= 0) { builder.setConnectionRequestTimeout(connectionRequestTimeout); } int socketTimeout = this.requestConfig.getSocketTimeout(); if (socketTimeout >= 0) { builder.setSocketTimeout(socketTimeout); } return builder.build(); }

上例中虽然没有指定http连接池,但** HttpComponentsClientHttpRequestFactory无参构造会创建一个HttpClient,并默认使用了连接池配置,MaxTotal=10,DefaultMaxPerRoute=5 **,具体如下:

HttpComponentsClientHttpRequestFactory: /** * Create a new instance of the {@code HttpComponentsClientHttpRequestFactory} * with a default {@link HttpClient}. */ public HttpComponentsClientHttpRequestFactory() { this(HttpClients.createSystem()); } HttpClients: /** * Creates {@link CloseableHttpClient} instance with default * configuration based on system properties. * 创建CloseableHttpClient实例使用基于system properties的默认配置 */ public static CloseableHttpClient createSystem() { return HttpClientBuilder.create().useSystemProperties().build(); } HttpClientBuilder: /** * Use system properties when creating and configuring default * implementations. */ public final HttpClientBuilder useSystemProperties() { this.systemProperties = true; //设置systemProperties为true return this; } public CloseableHttpClient build() { HttpClientConnectionManager connManagerCopy = this.connManager; //没有设置,为null if (connManagerCopy == null) { 。。。。。。 //创建连接池管理器PoolingHttpClientConnectionManager @SuppressWarnings("resource") final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager( RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslSocketFactoryCopy) .build(), null, null, dnsResolver, connTimeToLive, connTimeToLiveTimeUnit != null ? connTimeToLiveTimeUnit : TimeUnit.MILLISECONDS); if (defaultSocketConfig != null) { poolingmgr.setDefaultSocketConfig(defaultSocketConfig); } if (defaultConnectionConfig != null) { poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig); } //由于是HttpClientBuilder.create().useSystemProperties().build(),systemProperties为true if (systemProperties) { String s = System.getProperty("http.keepAlive", "true"); //http.keepAlive默认值为true if ("true".equalsIgnoreCase(s)) { s = System.getProperty("http.maxConnections", "5"); //默认值为5 final int max = Integer.parseInt(s); poolingmgr.setDefaultMaxPerRoute(max); //DefaultMaxPerRoute=5 poolingmgr.setMaxTotal(2 * max); //MaxTotal=10 } } if (maxConnTotal > 0) { poolingmgr.setMaxTotal(maxConnTotal); } if (maxConnPerRoute > 0) { poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute); } connManagerCopy = poolingmgr; } } 配置连接池 @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(clientHttpRequestFactory()); } @Bean public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() { try { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //开始设置连接池 PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(); poolingHttpClientConnectionManager.setMaxTotal(100); //最大连接数 poolingHttpClientConnectionManager.setDefaultMaxPerRoute(20); //同路由并发数 httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager); HttpClient httpClient = httpClientBuilder.build(); // httpClient连接配置 HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); clientHttpRequestFactory.setConnectTimeout(30 * 1000); //连接超时 clientHttpRequestFactory.setReadTimeout(60 * 1000); //数据读取超时时间 clientHttpRequestFactory.setConnectionRequestTimeout(30 * 1000); //连接不够用的等待时间 return clientHttpRequestFactory; } catch (Exception e) { logger.error("初始化clientHttpRequestFactory出错", e); } return null; } } 3、自定义messageConverter

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwyjgd.html