Spring中RestTemplate进行Http调用

Spring中的RestTemplate类源自spring-web,http调用中设置超时时间、设置连接池管理等非常重要,保证了系统的可用性,避免了长时间连接不上或者等待数据返回,拖垮系统。

现贴出工作上关于RestTemplate的标准配置,设置了超时时间、连接池等,开箱即用。

package com.pab.bloan.charge.app.common.config;

import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
public class RestTemplateConfig {

    private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100;

    private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 10;

    private static final int DEFAULT_MAX_TIME_OUT = 3000;

    @Value("${rest-template.timeout:3000}")
    private int defaultTimeOut;

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory());
        List<HttpMessageConverter<?>> converters = new ArrayList<>();
        FastJsonHttpMessageConverter jacksonMessageConverter = new FastJsonHttpMessageConverter();
        converters.add(jacksonMessageConverter);
        restTemplate.setMessageConverters(converters);
        return restTemplate;
    }

    @Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        RequestConfig requestConfig = RequestConfig.custom()
                // 连接超时
                .setConnectTimeout(defaultTimeOut)
                // 排队超时
                .setConnectionRequestTimeout(defaultTimeOut)
                // 数据读取超时
                .setSocketTimeout(defaultTimeOut)
                .build();
        requestFactory.setConnectTimeout(defaultTimeOut);
        requestFactory.setReadTimeout(defaultTimeOut);
        SocketConfig socketConfig = SocketConfig
                .custom()
                .setSoKeepAlive(false)
                .setTcpNoDelay(true)
                .build();
        PoolingHttpClientConnectionManager pm = new PoolingHttpClientConnectionManager();
        pm.setDefaultSocketConfig(socketConfig);
        pm.closeIdleConnections(DEFAULT_MAX_TIME_OUT, TimeUnit.MICROSECONDS);
        pm.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);
        pm.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(pm)
                .build();
        requestFactory.setHttpClient(httpClient);
        return requestFactory;
    }
}

使用示例(代码中将相关的请求url、请求参数、响应参数,替换掉即可):

/**
     * 调用渠道查询客户经理名单接口
     * @param saleManagerRequest
     * @return
     */
    private SaleManagerResponse requestQDSaleManagerApi(SaleManagerRequest saleManagerRequest) {
        // 调用外联额度变更接口
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        ResponseEntity<SaleManagerResponse> responseEntity =
                restTemplate.postForEntity(accessGatewayService.getAccessGatewayRequestUrl(qdSaleManagerSearchUrl),
                        new HttpEntity<>(saleManagerRequest, headers), SaleManagerResponse.class);

        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            SaleManagerResponse saleManagerResponse = responseEntity.getBody();
            if (saleManagerResponse != null
                    && Response.SUCCESS.equals(saleManagerResponse.getResponseCode())) {
                return saleManagerResponse;
            } else {
                log.error("request destination error:[requestUrl:{}; request:{}; response:{}]",
                        new Object[]{qdSaleManagerSearchUrl, saleManagerRequest, saleManagerResponse});
                throw new BusinessException("调用渠道查询客户经理名单接口异常");
            }
        } else {
            throw new BusinessException("调用渠道查询客户经理名单接口网络不可达");
        }
    }

标准化代码,用起来美滋滋。

 

posted @ 2019-04-01 14:52  嘟神子  阅读(1878)  评论(0编辑  收藏  举报