记录如何使用Spring中的RestTemplate(with apache.httpcomponents)发起 REST API请求
REQUIREMENTS
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.6</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
|
SETTING UP
HttpConfigProperties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| @Component @Data public class HttpConfigProperties {
private Integer maxTotalConnections = 200; private Integer maxPerRoute = 100; /** * 等待连接建立的超时时间 5秒 */ private Integer connectTimeout = 5000;
/** * 等待数据传输的超时时间 15秒 */ private Integer socketTimeout = 15000;
/** * 等待请求连接池的超时时间 5秒 */ private Integer connectionRequestTimeout = 5000;
/** * 允许连接idle的时间 10秒 */ private Integer keeAliveTimeMillis = 10000;
/** * idle最大时间 */ private Integer closeIdleConnectionWaitTimeSecs = 20;
}
|
HttpClientPoolingConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| @Configuration @EnableScheduling @Slf4j public class HttpClientPoolingConfig {
@Resource private HttpConfigProperties properties;
@Bean(name = "poolingConnectionManager") public PoolingHttpClientConnectionManager poolingConnectionManager() { try { LayeredConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault()); Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("https", sslsf) .register("http", new PlainConnectionSocketFactory()) .build(); PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); poolingConnectionManager.setMaxTotal(properties.getMaxTotalConnections()); poolingConnectionManager.setDefaultMaxPerRoute(properties.getMaxPerRoute()); return poolingConnectionManager; } catch (Exception e) { log.error("Pooling Connection Manager Initialisation failure because of " + e.getMessage(), e); throw new RuntimeException(); }
}
@Bean(name = "connectionKeepAliveStrategy") public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() { return (response, context) -> { HeaderElementIterator it = new BasicHeaderElementIterator (response.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { HeaderElement he = it.nextElement(); String param = he.getName(); String value = he.getValue();
if (value != null && param.equalsIgnoreCase("timeout")) { return Long.parseLong(value) * 1000; } } return properties.getKeeAliveTimeMillis(); }; }
@Bean(name = "httpClient") public CloseableHttpClient httpClient(@Qualifier(value = "connectionKeepAliveStrategy") ConnectionKeepAliveStrategy connectionKeepAliveStrategy) { RequestConfig requestConfig = RequestConfig.custom() .setConnectionRequestTimeout(properties.getConnectionRequestTimeout()) .setConnectTimeout(properties.getConnectTimeout()) .setSocketTimeout(properties.getSocketTimeout()).build();
return HttpClients.custom() .setDefaultRequestConfig(requestConfig) .setConnectionManager(poolingConnectionManager()) .setKeepAliveStrategy(connectionKeepAliveStrategy) .build(); }
@Bean public Runnable idleConnectionMonitor(@Qualifier(value = "poolingConnectionManager") PoolingHttpClientConnectionManager poolingConnectionManager) { return new Runnable() { @Override @Scheduled(fixedDelay = 10000, initialDelay = 1000) public void run() { try { if (poolingConnectionManager != null) { log.info("run IdleConnectionMonitor - Closing expired and idle connections..."); poolingConnectionManager.closeExpiredConnections(); poolingConnectionManager.closeIdleConnections(properties.getCloseIdleConnectionWaitTimeSecs(), TimeUnit.SECONDS); } else { log.info("run IdleConnectionMonitor - Http Client Connection manager is not initialised"); } } catch (Exception e) { log.error("run IdleConnectionMonitor - Exception occurred. msg={}, e={}", e.getMessage(), e); } } }; }
}
|
RestTemplateConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Configuration @Slf4j public class RestTemplateConfig {
@Bean public RestTemplate restTemplate(@Qualifier(value = "httpClient") CloseableHttpClient httpClient) { HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory); List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors(); if (CollectionUtils.isEmpty(interceptors)) { interceptors = new ArrayList<>(); } interceptors.add(new RestTemplateLogInterceptor()); restTemplate.setInterceptors(interceptors); restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8"))); return restTemplate; }
}
|
RestTemplateLogInterceptor
1 2 3 4 5 6 7 8 9 10 11 12
| @Slf4j public class RestTemplateLogInterceptor implements ClientHttpRequestInterceptor {
@Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { ClientHttpResponse response = execution.execute(request, body); if (response.getStatusCode() != HttpStatus.OK) { log.error("RESTful api error, request is {} ,response is {}", request.getURI(), response.getStatusCode()); } return response; } }
|
DEMO
I’m just a girl, standing in front of a boy, asking him to love her. - Allie
The Notebook