Spring Boot 之 RestTemplate 连接池配置

RestTemplate 连接池配置

RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

RestTemplate的默认连接池是 SimpleClientHttpRequestFactory

自定义连接池如下所示

配置文件类

    /**
     * RestTemplate 客户端 Httpclient 的线程池配置
     *
     * @author fengxuechao
     * @version 0.1
     * @date 2019/11/12
     */
    @ConfigurationProperties(prefix = "http-pool")
    @Data
    public class HttpPoolProperties {
    
        /**
         * 最大线程数
         */
        private Integer maxTotal = 20;
    
        /**
         * 默认线程数
         */
        private Integer defaultMaxPerRoute = 10;
    
        /**
         * 连接上服务器(握手成功)的时间
         */
        private Integer connectTimeout = 1000;
    
        /**
         * 从连接池中获取连接的超时时间
         */
        private Integer connectionRequestTimeout = 3000;
    
        /**
         * 服务器返回数据(response)的时间
         */
        private Integer socketTimeout = 5000;
    
        /**
         * 用于校验线程空闲的时间
         */
        private Integer validateAfterInactivity = 7000;
    
        /**
         * 开启异步线程池
         */
        private Boolean async = false;
    
    }

连接池配置类

忽略SSL

    /**
     * @author fengxuechao
     * @version 0.1
     * @date 2019/12/17
     */
    @Slf4j
    @Component
    public class HttpClientHelper {
    
        public SSLContext getSslContext() {
            // 在调用SSL之前需要重写验证方法,取消检测SSL
            X509TrustManager trustManager = new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
    
                @Override
                public void checkClientTrusted(X509Certificate[] xcs, String str) {
                }
    
                @Override
                public void checkServerTrusted(X509Certificate[] xcs, String str) {
                }
            };
            SSLContext ctx = null;
            try {
                ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
                ctx.init(null, new TrustManager[]{trustManager}, null);
            } catch (NoSuchAlgorithmException | KeyManagementException e) {
                log.error("创建 SSL 失败", e);
            }
            assert ctx != null;
            return ctx;
        }
    
    }

配置类

    /**
     * HttpClient 的配置
     *
     * @author fengxuechao
     * @version 0.1
     * @date 2019/11/12
     */
    @Slf4j
    @Configuration
    @ConditionalOnClass({HttpClient.class})
    @EnableConfigurationProperties(HttpPoolProperties.class)
    public class HttpClientConfig {
    
        @Autowired
        private HttpPoolProperties httpPoolProperties;
    
        @Autowired
        private HttpClientHelper helper;
    
        @Bean("httpRequestFactory")
        @ConditionalOnMissingBean
        public ClientHttpRequestFactory httpRequestFactory() {
            return new HttpComponentsClientHttpRequestFactory(httpClient());
        }
    
        @Bean("httpClient")
        @ConditionalOnMissingBean
        public HttpClient httpClient() {
            // 在调用SSL之前需要重写验证方法,取消检测SSL
            X509TrustManager trustManager = new X509TrustManager() {
                @Override public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                @Override public void checkClientTrusted(X509Certificate[] xcs, String str) {}
                @Override public void checkServerTrusted(X509Certificate[] xcs, String str) {}
            };
            SSLConnectionSocketFactory socketFactory = null;
            try {
                SSLContext ctx = helper.getSslContext();
                ctx.init(null, new TrustManager[] { trustManager }, null);
                socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
            } catch (KeyManagementException e) {
                log.error("创建 SSL 失败", e);
            }
    
            assert socketFactory != null;
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", socketFactory)
                    .build();
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
            connectionManager.setMaxTotal(httpPoolProperties.getMaxTotal());
            connectionManager.setDefaultMaxPerRoute(httpPoolProperties.getDefaultMaxPerRoute());
            connectionManager.setValidateAfterInactivity(httpPoolProperties.getValidateAfterInactivity());
            RequestConfig requestConfig = RequestConfig.custom()
                    //服务器返回数据(response)的时间,超过抛出read timeout
                    .setSocketTimeout(httpPoolProperties.getSocketTimeout())
                    //连接上服务器(握手成功)的时间,超出抛出connect timeout
                    .setConnectTimeout(httpPoolProperties.getConnectTimeout())
                    //从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                    .setConnectionRequestTimeout(httpPoolProperties.getConnectionRequestTimeout())
                    .build();
            return HttpClientBuilder.create()
                    .setDefaultRequestConfig(requestConfig)
                    .setConnectionManager(connectionManager)
                    .build();
        }
    }

RestTemplate 配置

    /**
     * @author fengxuechao
     * @version 0.1
     * @date 2019/11/12
     */
    @Configuration
    @Import({HttpClientConfig.class})
    public class RestTemplateConfiguration {
    
        /**
         * 普通的 RestTemplate
         *
         * @return
         */
        @Bean("restTemplate")
        @ConditionalOnMissingBean
        @ConditionalOnBean(value = ClientHttpRequestFactory.class)
        public RestTemplate restTemplate(ClientHttpRequestFactory httpRequestFactory) {
            RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
            restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            return restTemplate;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值