<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.10</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
2. Java配置类
java
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "http-pool") @Data public class HttpPoolProperties { private Integer maxTotal; private Integer defaultMaxPerRoute; private Integer connectTimeout; private Integer connectionRequestTimeout; private Integer socketTimeout; private Integer validateAfterInactivity; }
import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.springframework.beans.factory.annotation.Autowired; 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.web.client.RestTemplate; @Configuration public class HttpClientRestTemplateConfig { @Autowired private HttpPoolProperties httpPoolProperties; @Bean("httpClientRestTemplate") public RestTemplate httpClientRestTemplate() { HttpClient httpClient = httpClient(); ClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); RestTemplate restTemplate = new RestTemplate(factory); // 能够添加消息转换 //restTemplate.setMessageConverters(...); // 能够增长拦截器 //restTemplate.setInterceptors(...); return restTemplate; } @Bean public HttpClient httpClient() { Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", SSLConnectionSocketFactory.getSocketFactory()) .build(); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); // 设置整个链接池最大链接数 根据本身的场景决定 connectionManager.setMaxTotal(httpPoolProperties.getMaxTotal()); // 设置每一个路由(域名)最大的线程数 connectionManager.setDefaultMaxPerRoute(httpPoolProperties.getDefaultMaxPerRoute()); // 设置路由(域名)对应的最大线程数,若是设置则比setDefaultMaxPerRoute(xxx)的优先级高 //connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost("v2.moon.com", 80)), 20); // validateAfterInactivity 空闲永久链接检查间隔,这个牵扯的还比较多, // 官方推荐使用这个来检查永久连接的可用性,而不推荐每次请求的时候才去检查 connectionManager.setValidateAfterInactivity(httpPoolProperties.getValidateAfterInactivity()); RequestConfig requestConfig = RequestConfig.custom() // 链接上服务器(握手成功)的时间(能够设置2000),超出抛出connect timeout .setConnectTimeout(httpPoolProperties.getConnectTimeout()) // 服务器返回数据(response)的时间(能够设置3000),超过抛出read timeout .setSocketTimeout(httpPoolProperties.getSocketTimeout()) // 从链接池中获取链接的超时时间,超时间未拿到可用链接,会抛出如下异常 //org.apache.http.conn.ConnectionPoolTimeoutException: //Timeout waiting for connection from pool .setConnectionRequestTimeout(httpPoolProperties.getConnectionRequestTimeout()) .build(); // 重试一次 DefaultHttpRequestRetryHandler requestRetryHandler = new DefaultHttpRequestRetryHandler(1, true, new ArrayList<>()) { public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { LOGGER.info("Retry request, execution count: {}, exception: {}", executionCount, exception); return super.retryRequest(exception, executionCount, context); } }; return HttpClientBuilder.create() .setDefaultRequestConfig(requestConfig) .setConnectionManager(connectionManager) .setRetryHandler(requestRetryHandler) .build(); } }
3.使用方法web
import org.json.JSONException; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.io.IOException; @Service public class TestService { @Autowired private RestTemplate restTemplate; public void startTest() throws JSONException, IOException { JSONObject jsonObject = new JSONObject(); jsonObject.put("first","jinjian"); jsonObject.put("second","aaaaaaa"); long start = System.currentTimeMillis(); //{1} 表示第一个占位符,也能够填写name,可是这是另外一个getForEntity重载方法 //TestResponseEntity 为自定义dto ResponseEntity<TestResponseEntity> entity = restTemplate.getForEntity("http://39.107.104.221/api/test/{1}", TestResponseEntity.class, 123); long end = System.currentTimeMillis(); long cost = end - start; System.out.println("耗时:"+cost); RuiooResponseEntity body = entity.getBody(); body.getData(); body.getStatus(); body.getMessage(); System.out.println("响应体:"+ body); } }