Last active
July 24, 2021 04:14
-
-
Save mingyu-kwak/afd93109c0c3798bec059277f003b69d to your computer and use it in GitHub Desktop.
Apache HttpComponents를 이용한 RestTemplate Bean 등록
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package local.mike.simpleboard.configure; | |
| import lombok.extern.slf4j.Slf4j; | |
| import org.apache.http.client.HttpClient; | |
| import org.apache.http.client.config.RequestConfig; | |
| import org.apache.http.conn.HttpClientConnectionManager; | |
| import org.apache.http.impl.client.HttpClients; | |
| import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; | |
| import org.springframework.beans.factory.annotation.Value; | |
| import org.springframework.boot.web.client.RestTemplateBuilder; | |
| import org.springframework.context.annotation.Bean; | |
| import org.springframework.context.annotation.Configuration; | |
| import org.springframework.http.client.*; | |
| import org.springframework.web.client.RestTemplate; | |
| import java.time.Duration; | |
| import java.util.concurrent.TimeUnit; | |
| /** | |
| * <p><b> | |
| * HTTP 상의 Rest API를 호출하기 위해 RestTemplate 객체를 설정하고 Bean 등록하는 클래스. | |
| * </b></p> | |
| * | |
| * Database 연결 시 사용하는 Connection Pool과 같이 Http Client도 Connection Pool을 만들어 | |
| * 사용해야 많은 요청 시 소켓을 미리 확보 및 제한해 효율적으로 통신할 수 있도록 | |
| * 만들어 줄 수 있다. | |
| * | |
| * 아래는 Apache HttpComponents Library를 이용해 커넥션 풀을 만들어 RequestFactory에 등록하고 | |
| * Interceptor를 사용해 Log 정보를 출력하는 RestTemplate 객체를 만들어 Bean으로 등록해 둔다. | |
| */ | |
| @Configuration | |
| @Slf4j | |
| public class HttpClientConfiguration { | |
| private final int readTimeoutSeconds; | |
| private final int connectTimeoutSeconds; | |
| private final int maxIdleConnections; | |
| private final int keepAliveMinutes; | |
| public HttpClientConfiguration(@Value("${http-client.read-timeout-seconds}") int readTimeoutSeconds, | |
| @Value("${http-client.connect-timeout-seconds}") int connectTimeoutSeconds, | |
| @Value("${http-client.max-idle-connections}") int maxIdleConnections, | |
| @Value("${http-client.keep-alive-minutes}") int keepAliveMinutes) { | |
| this.readTimeoutSeconds = readTimeoutSeconds; | |
| this.connectTimeoutSeconds = connectTimeoutSeconds; | |
| this.maxIdleConnections = maxIdleConnections; | |
| this.keepAliveMinutes = keepAliveMinutes; | |
| } | |
| private HttpClientConnectionManager httpClientConnectionManager() { | |
| PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(); | |
| manager.closeIdleConnections(keepAliveMinutes, TimeUnit.MINUTES); | |
| manager.setMaxTotal(maxIdleConnections); | |
| manager.setDefaultMaxPerRoute(5); | |
| return manager; | |
| } | |
| private RequestConfig requestConfig() { | |
| return RequestConfig.custom() | |
| .setConnectionRequestTimeout(connectTimeoutSeconds) | |
| .setConnectTimeout(connectTimeoutSeconds) | |
| .setSocketTimeout(connectTimeoutSeconds) | |
| .build(); | |
| } | |
| @Bean | |
| public HttpClient httpClient() { | |
| return HttpClients.custom() | |
| .setConnectionManager(httpClientConnectionManager()) | |
| .setDefaultRequestConfig(requestConfig()) | |
| .disableCookieManagement() | |
| .build(); | |
| } | |
| /** | |
| * RestTemplateBuilder를 통해 HttpClient를 이용한 ClientHttpRequestFactory와 | |
| * 아래서 설정한 Log를 찍기 위한 Interceptor를 설정한다. | |
| * @param httpClient HttpClient 객체 | |
| * @return 서비스에서 호출 가능한 RestTemplate 객체 | |
| */ | |
| @Bean | |
| public RestTemplate restTemplate(HttpClient httpClient) { | |
| return new RestTemplateBuilder() | |
| .setReadTimeout(Duration.ofSeconds(readTimeoutSeconds)) | |
| .requestFactory(() -> new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient))) | |
| .interceptors(clientHttpRequestInterceptor()) | |
| .build(); | |
| } | |
| /** | |
| * HTTP Client 사용 시 Log를 찍기 위한 Interceptor 객체. | |
| * ClientHttpRequestInterceptor 인터페이스를 람다로 통해 익명 객체화 하여 리턴한다. | |
| * @return Log를 찍기 위한 로직이 들어있는 ClientHttpRequestInterceptor 익명 객체 | |
| */ | |
| private ClientHttpRequestInterceptor clientHttpRequestInterceptor() { | |
| return (httpRequest, bodyBytes, execution) -> { | |
| if (log.isDebugEnabled()) { | |
| log.debug("HttpClientRequest {} {}, body: {}", httpRequest.getMethodValue(), httpRequest.getURI(), bodyBytes); | |
| } | |
| ClientHttpResponse execute = execution.execute(httpRequest, bodyBytes); | |
| if (log.isDebugEnabled()) { | |
| log.debug("HttpClientResponse state: {}", execute.getRawStatusCode()); | |
| log.debug("HttpClientResponse body: {}", execute.getBody()); | |
| } | |
| return execute; | |
| }; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment