packagecom.config;importorg.apache.hc.client5.http.auth.CredentialsProvider;importorg.apache.hc.client5.http.auth.StandardAuthScheme;importorg.apache.hc.client5.http.config.ConnectionConfig;importorg.apache.hc.client5.http.config.RequestConfig;importorg.apache.hc.client5.http.config.TlsConfig;importorg.apache.hc.client5.http.cookie.BasicCookieStore;importorg.apache.hc.client5.http.cookie.CookieStore;importorg.apache.hc.client5.http.cookie.StandardCookieSpec;importorg.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;importorg.apache.hc.client5.http.impl.classic.CloseableHttpClient;importorg.apache.hc.client5.http.impl.classic.HttpClients;importorg.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;importorg.apache.hc.core5.http.io.SocketConfig;importorg.apache.hc.core5.http.ssl.TLS;importorg.apache.hc.core5.util.TimeValue;importorg.apache.hc.core5.util.Timeout;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.Primary;importorg.springframework.http.client.ClientHttpRequestFactory;importorg.springframework.http.client.HttpComponentsClientHttpRequestFactory;importorg.springframework.http.converter.HttpMessageConverter;importorg.springframework.http.converter.StringHttpMessageConverter;importorg.springframework.web.client.RestTemplate;importjava.nio.charset.Charset;importjava.util.Arrays;importjava.util.Collections;importjava.util.List;@ConfigurationpublicclassRestTemplateConfig{@BeanpublicRestTemplaterestTemplate(ClientHttpRequestFactory clientHttpRequestFactory){RestTemplate restTemplate =newRestTemplate(clientHttpRequestFactory);List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();for(HttpMessageConverter c : messageConverters){if(c instanceofStringHttpMessageConverter){((StringHttpMessageConverter) c).setDefaultCharset(Charset.forName("utf-8"));}}return restTemplate;}@Bean@PrimarypublicClientHttpRequestFactoryclientHttpRequestFactory(){finalPoolingHttpClientConnectionManager connManager =newPoolingHttpClientConnectionManager();
connManager.setDefaultSocketConfig(SocketConfig.custom().setTcpNoDelay(true).build());// Validate connections after 10 sec of inactivity
connManager.setDefaultConnectionConfig(ConnectionConfig.custom().setConnectTimeout(Timeout.ofMilliseconds(3000))//确定新连接完全建立之前的超时时间。.setSocketTimeout(Timeout.ofMilliseconds(5000)).setTimeToLive(TimeValue.ofHours(1)).build());// Configure total max or per route limits for persistent connections// that can be kept in the pool or leased by the connection manager.
connManager.setMaxTotal(200);
connManager.setDefaultMaxPerRoute(128);finalCookieStore cookieStore =newBasicCookieStore();// Use custom credentials provider if necessary.finalCredentialsProvider credentialsProvider =CredentialsProviderBuilder.create().build();// Create global request configurationfinalRequestConfig defaultRequestConfig =RequestConfig.custom().setConnectionRequestTimeout(Timeout.ofMilliseconds(30000))//请求超时时间.setResponseTimeout(Timeout.ofMilliseconds(10000)).setCookieSpec(StandardCookieSpec.STRICT).setExpectContinueEnabled(true).setTargetPreferredAuthSchemes(Arrays.asList(StandardAuthScheme.NTLM,StandardAuthScheme.DIGEST)).setProxyPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.BASIC)).build();CloseableHttpClient httpClient =HttpClients.custom().setConnectionManager(connManager).setDefaultCookieStore(cookieStore).setDefaultCredentialsProvider(credentialsProvider).setDefaultRequestConfig(defaultRequestConfig).build();HttpComponentsClientHttpRequestFactory factory =newHttpComponentsClientHttpRequestFactory(httpClient);return factory;}}
3. CloseableHttpClient配置详细介绍
packagecom.config;importorg.apache.hc.client5.http.DnsResolver;importorg.apache.hc.client5.http.HttpRoute;importorg.apache.hc.client5.http.SystemDefaultDnsResolver;importorg.apache.hc.client5.http.auth.CredentialsProvider;importorg.apache.hc.client5.http.auth.StandardAuthScheme;importorg.apache.hc.client5.http.config.ConnectionConfig;importorg.apache.hc.client5.http.config.RequestConfig;importorg.apache.hc.client5.http.config.TlsConfig;importorg.apache.hc.client5.http.cookie.BasicCookieStore;importorg.apache.hc.client5.http.cookie.CookieStore;importorg.apache.hc.client5.http.cookie.StandardCookieSpec;importorg.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;importorg.apache.hc.client5.http.impl.classic.CloseableHttpClient;importorg.apache.hc.client5.http.impl.classic.HttpClients;importorg.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory;importorg.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;importorg.apache.hc.client5.http.io.ManagedHttpClientConnection;importorg.apache.hc.client5.http.socket.ConnectionSocketFactory;importorg.apache.hc.client5.http.socket.PlainConnectionSocketFactory;importorg.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;importorg.apache.hc.core5.http.*;importorg.apache.hc.core5.http.config.CharCodingConfig;importorg.apache.hc.core5.http.config.Http1Config;importorg.apache.hc.core5.http.config.Registry;importorg.apache.hc.core5.http.config.RegistryBuilder;importorg.apache.hc.core5.http.impl.io.DefaultClassicHttpResponseFactory;importorg.apache.hc.core5.http.impl.io.DefaultHttpRequestWriterFactory;importorg.apache.hc.core5.http.impl.io.DefaultHttpResponseParser;importorg.apache.hc.core5.http.impl.io.DefaultHttpResponseParserFactory;importorg.apache.hc.core5.http.io.*;importorg.apache.hc.core5.http.message.BasicHeader;importorg.apache.hc.core5.http.message.BasicLineParser;importorg.apache.hc.core5.http.message.LineParser;importorg.apache.hc.core5.http.ssl.TLS;importorg.apache.hc.core5.pool.PoolConcurrencyPolicy;importorg.apache.hc.core5.pool.PoolReusePolicy;importorg.apache.hc.core5.ssl.SSLContexts;importorg.apache.hc.core5.util.CharArrayBuffer;importorg.apache.hc.core5.util.TimeValue;importorg.apache.hc.core5.util.Timeout;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.Primary;importjavax.net.ssl.SSLContext;importjava.net.InetAddress;importjava.net.UnknownHostException;importjava.nio.charset.CodingErrorAction;importjava.nio.charset.StandardCharsets;importjava.util.Arrays;importjava.util.Collections;@ConfigurationpublicclassHttpClientConfig{@Bean@PrimarypublicCloseableHttpClienthttpClient(){// Use custom message parser / writer to customize the way HTTP// messages are parsed from and written out to the data stream.// (使用自定义消息解析器/编写器来自定义从数据流解析HTTP消息和将其写入数据流的方式。)finalHttpMessageParserFactory<ClassicHttpResponse> responseParserFactory =newDefaultHttpResponseParserFactory(){@OverridepublicHttpMessageParser<ClassicHttpResponse>create(finalHttp1Config h1Config){finalLineParser lineParser =newBasicLineParser(){@OverridepublicHeaderparseHeader(finalCharArrayBuffer buffer){try{returnsuper.parseHeader(buffer);}catch(finalParseException ex){returnnewBasicHeader(buffer.toString(),null);}}};returnnewDefaultHttpResponseParser(lineParser,DefaultClassicHttpResponseFactory.INSTANCE, h1Config);}};finalHttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory =newDefaultHttpRequestWriterFactory();// Create HTTP/1.1 protocol configuration (创建HTTP1.1协议配置,基本用不到)finalHttp1Config h1Config =Http1Config.custom().setMaxHeaderCount(200)//.setMaxLineLength(2000).build();// Create connection configuration (创建连接配置)finalCharCodingConfig connectionConfig =CharCodingConfig.custom().setMalformedInputAction(CodingErrorAction.IGNORE)//该方法用于设置字符编码遇到错误输入时的处理行为,IGNORE:忽略错误输入,继续进行字符编码。.setUnmappableInputAction(CodingErrorAction.IGNORE)//用于设置字符编码遇到无法映射的输入时的处理行为.setCharset(StandardCharsets.UTF_8)//设置字符编码。可以指定请求和响应的字符编码.build();// Use a custom connection factory to customize the process of// initialization of outgoing HTTP connections. Beside standard connection// configuration parameters HTTP connection factory can define message// parser / writer routines to be employed by individual connections.// (使用自定义连接工厂来自定义传出HTTP连接的初始化过程。除了标准连接配置参数之外,HTTP连接工厂还可以定义单个连接所使用的消息解析器/编写器例程。)// 通常情况下,不需要直接使用 HttpConnectionFactory 接口,而是通过 HttpClient 配置来创建 HTTP 连接finalHttpConnectionFactory<ManagedHttpClientConnection> connFactory =newManagedHttpClientConnectionFactory(
h1Config, connectionConfig, requestWriterFactory, responseParserFactory);//通过连接工厂创建连接// ManagedHttpClientConnection connection = connFactory.createConnection(Socket var1);// Client HTTP connection objects when fully initialized can be bound to// an arbitrary network socket. The process of network socket initialization,// its connection to a remote address and binding to a local one is controlled// by a connection socket factory.//(客户端HTTP连接对象在完全初始化时可以绑定到任意网络套接字。网络套接字初始化、连接到远程地址和绑定到本地地址的过程由连接套接字工厂控制。)// SSL context for secure connections can be created either based on// system or application specific properties.//(安全连接的SSL上下文可以基于系统或应用程序特定的属性创建。)finalSSLContext sslContext =SSLContexts.createSystemDefault();// Create a registry of custom connection socket factories for supported// protocol schemes.//(为支持的协议方案创建自定义连接套接字工厂的注册表。)finalRegistry<ConnectionSocketFactory> socketFactoryRegistry =RegistryBuilder.<ConnectionSocketFactory>create().register("http",PlainConnectionSocketFactory.INSTANCE).register("https",newSSLConnectionSocketFactory(sslContext)).build();// Use custom DNS resolver to override the system DNS resolution.// 使用自定义 DNS 解析器覆盖系统 DNS 解析。finalDnsResolver dnsResolver =newSystemDefaultDnsResolver(){@OverridepublicInetAddress[]resolve(finalString host)throwsUnknownHostException{if(host.equalsIgnoreCase("myhost")){returnnewInetAddress[]{InetAddress.getByAddress(newbyte[]{127,0,0,1})};}else{returnsuper.resolve(host);}}};// Create a connection manager with custom configuration.// 使用自定义配置创建连接管理器。// PoolConcurrencyPolicy 连接池的并发性策略 STRICT:严格模式,在并发访问连接时,只有一个线程可以访问连接 LENIENT:宽松模式,在并发访问连接时,允许多个线程同时访问连接// PoolReusePolicy 连接池的连接重用策略:LIFO:后进先出,连接池返回连接时,优先选择最近返回的连接进行复用。 FIFO:先进先出,连接池返回连接时,优先选择最早返回的连接进行复用// TimeValue.ofMinutes(5) 时间值类型,用于设置连接在连接池中的最大空闲时间// dnsResolver DNS 解析器,用于解析主机名到 IP 地址finalPoolingHttpClientConnectionManager connManager =newPoolingHttpClientConnectionManager(
socketFactoryRegistry,PoolConcurrencyPolicy.STRICT,PoolReusePolicy.LIFO,TimeValue.ofMinutes(5),null, dnsResolver,null);// Configure the connection manager to use socket configuration either// by default or for a specific host.// (将连接管理器配置为在默认情况下或针对特定主机使用套接字配置。)
connManager.setDefaultSocketConfig(SocketConfig.custom().setTcpNoDelay(true).build());// Validate connections after 10 sec of inactivity// 10 秒不活动后验证连接
connManager.setDefaultConnectionConfig(ConnectionConfig.custom().setConnectTimeout(Timeout.ofSeconds(30))//与服务端建立连接超时时间.setSocketTimeout(Timeout.ofSeconds(30))// 设置套接字超时时间,即等待响应数据的超时时间。.setValidateAfterInactivity(TimeValue.ofSeconds(10))// 连接验证间隔时间。当一个连接在池中空闲时间超过此值时,连接将被验证是否可用.setTimeToLive(TimeValue.ofHours(1))//定义连接可以保持活动状态或执行请求的总时间跨度。.build());// Use TLS v1.3 only// 仅使用 TLS v1.3
connManager.setDefaultTlsConfig(TlsConfig.custom()//用于配置 TLS 相关的参数.setHandshakeTimeout(Timeout.ofSeconds(30))//设置 TLS 握手超时时间.setSupportedProtocols(TLS.V_1_3)//设置 TLS 握手超时时间.build());// Configure total max or per route limits for persistent connections// that can be kept in the pool or leased by the connection manager.// 为可以保留在池中或由连接管理器租用的持久连接配置总的最大或每条路由限制。
connManager.setMaxTotal(100);
connManager.setDefaultMaxPerRoute(10);
connManager.setMaxPerRoute(newHttpRoute(newHttpHost("somehost",80)),20);// Use custom cookie store if necessary.// 如有必要,使用自定义 cookie 存储finalCookieStore cookieStore =newBasicCookieStore();// Use custom credentials provider if necessary.// 如有必要,请使用自定义凭据提供程序。finalCredentialsProvider credentialsProvider =CredentialsProviderBuilder.create().build();// Create global request configuration// 创建全局请求配置finalRequestConfig defaultRequestConfig =RequestConfig.custom().setCookieSpec(StandardCookieSpec.STRICT).setExpectContinueEnabled(true).setTargetPreferredAuthSchemes(Arrays.asList(StandardAuthScheme.NTLM,StandardAuthScheme.DIGEST)).setProxyPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.BASIC)).build();finalCloseableHttpClient httpClient =HttpClients.custom().setConnectionManager(connManager)//设置 HttpClient 的连接管理器.setDefaultCookieStore(cookieStore)//设置默认的 Cookie 存储.setDefaultCredentialsProvider(credentialsProvider)//设置默认的凭据提供器.setProxy(newHttpHost("myproxy",8080))//设置代理服务器.setDefaultRequestConfig(defaultRequestConfig)//设置默认的请求配置.build();return httpClient;}}