[Spring] Migrating from HttpClient 4 to HttpClient 5 (for self-signed certificates)
2024. 12. 4. 14:21ㆍJava
기존 HttpClient 4 소스
의존성
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
RestTemplate 설정
package example.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpClient;
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.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
@Configuration
@Slf4j
public class RestTemplateConfig {
@Bean
public HttpClient httpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// 모든 인증서를 신뢰하도록 설정한다
final SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(null, (X509Certificate[] chain, String authType) -> true).build();
// Https 인증 요청시 호스트네임 유효성 검사를 진행하지 않게 한다.
final SSLConnectionSocketFactory sslSocketFactory
= new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslSocketFactory)
.build();
final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
return HttpClientBuilder.create()
.setMaxConnTotal(100)
.setMaxConnPerRoute(80) // the total number of connections limit to a single port or url.
.setSSLContext(sslContext)
.setConnectionManager(connectionManager)
.build();
}
@Bean
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory(final HttpClient httpClient) {
final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5 * 1_000);
factory.setReadTimeout(30 * 1_000);
factory.setHttpClient(httpClient);
return factory;
}
@Bean
public RestTemplate restTemplate(HttpComponentsClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
}
HttpClient 5 소스
의존성
groupId가 다름 주의
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.4.1</version>
</dependency>
RestTemplate 설정
HttpClient에 세팅하던 설정들을 ConnectionManager가 담당하게 됨
package example.config;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.core5.util.TimeValue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;
@Configuration
public class RestTemplateConfig {
@Bean
public CloseableHttpClient httpClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
return HttpClients.custom()
.setConnectionManager(
PoolingHttpClientConnectionManagerBuilder.create()
// .setTlsSocketStrategy(DefaultClientTlsStrategy.createDefault())
.setTlsSocketStrategy(
// Https 인증 요청시 호스트네임 유효성 검사를 진행하지 않게 한다.
new DefaultClientTlsStrategy(
new SSLContextBuilder()
.loadTrustMaterial(null, (chain, authType) -> true)
.build(),
NoopHostnameVerifier.INSTANCE))
.setDefaultConnectionConfig(
ConnectionConfig.custom()
.setSocketTimeout(1500, TimeUnit.MILLISECONDS) // 읽기 시간
.setConnectTimeout(3000, TimeUnit.MILLISECONDS) // 연결 시간
.build())
.setMaxConnTotal(100) // 커넥션 풀 적용 (최대 오픈되는 커넥션 수)
.setMaxConnPerRoute(10) // 커넥션 풀 적용 (IP:포트 1쌍에 대해 수행할 연결 수 제한)
.build())
.evictIdleConnections(TimeValue.ofSeconds(10))
.build();
}
@Bean
public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory(final HttpClient httpClient) {
final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5 * 1_000);
factory.setReadTimeout(30 * 1_000);
factory.setHttpClient(httpClient);
return factory;
}
@Bean
public RestTemplate restTemplate(final HttpComponentsClientHttpRequestFactory clientHttpRequestFactory) {
return new RestTemplate(clientHttpRequestFactory);
}
}
'Java' 카테고리의 다른 글
[Java] 데이터베이스 연동하기 (0) | 2017.02.23 |
---|---|
[Java 예제] 채팅(chatting) (2) | 2017.02.22 |
[Java 예제] 로또(a lottery) (0) | 2017.02.13 |
[Java 예제] 홀수 마방진(a magic square of odd order) (3) | 2017.02.11 |
[Java 예제] 다이아몬드(a diamond) (0) | 2017.02.11 |