본문 바로가기
백엔드/Spring

[Spring] RestTemplate을 편리하게 사용하자 (샘플 포함)

by RoJae 2022. 6. 12.

🚀  들어가면서

  • RestTemplate을 구체화하면서, 편리하게 사용할 수 있도록 만들어보고 싶었다.
  • 통신 사이에 AOP를 구현하여, 요청과 응답의 URI, Body, Param, Header를 로깅하는 기능을 할까 하였지만..
  • RestTemplate에 인터셉터를 추가할 수 있는 함수가 있어서 적절히 사용했다.

⚙️ 소스코드

HttpHeader.java

  • HttpHeader이다. 가변적으로 추가하기 편하게 만들었다.
  • build() 함수를 통해서 호환이 가능한 Apache의 HttpHeaders로 변환이 가능하다.
@NoArgsConstructor
@AllArgsConstructor
public class HttpHeader {
    private MediaType mediaType;
    private Map<String, String> keyValue;

    public HttpHeader(MediaType mediaType){
        this.mediaType = mediaType;
        this.keyValue = new HashMap<String, String>();
    }

    public void addHeader(String key, String value){
        this.keyValue.put(key, value);
    }

    public void addHeader(Map<String, String> newKeyValue){
        newKeyValue.forEach(
                (key, value) -> this.keyValue.merge(key, value, (v1, v2) -> v2)
        );
    }

    public HttpHeaders build(){
        HttpHeaders build = new HttpHeaders();
        this.keyValue.forEach(build::add);
        return build;
    }
}

 

RestHttpClient.java

  • Http 통신에 필요한 정보를 담는 클래스이다.
  • 가변적으로 바디와 쿼리스트링을 담을 수 있도록 하였다.
  • 메소드 별로 필요한 정보가 다르기 때문에, 여러 생성자를 만들었다.
@Getter
public class RestHttpClient {
    private HttpMethod method;
    private String url;
    private MultiValueMap<String, String> params;
    private HttpHeader headers;

    public RestHttpClient(@NonNull HttpMethod method, @NonNull String url){
        this.method = method;
        this.url = url;
    }

    public RestHttpClient(@NonNull HttpMethod method, @NonNull String url, MultiValueMap<String, String> params){
        this.method = method;
        this.url = url;
        this.params = params;
    }

    public RestHttpClient(@NonNull HttpMethod method, @NonNull String url, HttpHeader headers){
        this.method = method;
        this.url = url;
        this.headers = headers;
    }

    public RestHttpClient(@NonNull HttpMethod method, @NonNull String url, MultiValueMap<String, String> params, HttpHeader headers){
        this.method = method;
        this.url = url;
        this.params = params;
        this.headers = headers;
    }

    public void addHeader(String key, String value){
        this.getHeaders().addHeader(key, value);
    }

    public void addHeader(Map<String, String> newKeyValue){
        this.getHeaders().addHeader(newKeyValue);
    }

    public void addParam(String key, String value){
        if(this.params == null)
            this.params = new LinkedMultiValueMap<String, String>();
        this.params.add(key, value);
    }

    public HttpEntity<MultiValueMap<String, String>> toEntity(){
        return new HttpEntity<MultiValueMap<String, String>>(this.params, this.headers.build());
    }
}

 

RestProvider.java

  • 이 클래스를 통해서, 통신이 가능하다.
  • 외부에서 send() 함수를 조립하여, 응답 객체로 변환이 가능하도록 하였다.
@Slf4j
@Component
@RequiredArgsConstructor
public class RestProvider {
    private final RestTemplate restTemplate;

    public <T> ResponseEntity<T> send(@NonNull HttpMethod httpMethod, String url, Class<T> responseClassType) {
        RestHttpClient client = new RestHttpClient(httpMethod, url);
        return this.send(client, responseClassType);
    }

    public <T> ResponseEntity<T> send(@NonNull HttpMethod httpMethod, String url,
                                      HttpHeader headers, Class<T> responseClassType) {
        RestHttpClient client = new RestHttpClient(httpMethod, url, headers);
        return this.send(client, responseClassType);
    }

    public <T> ResponseEntity<T> send(@NonNull HttpMethod httpMethod, String url,
                                      MultiValueMap<String, String> params, Class<T> responseClassType) {
        RestHttpClient client = new RestHttpClient(httpMethod, url, params);
        return this.send(client, responseClassType);
    }

    public <T> ResponseEntity<T> send(@NonNull HttpMethod httpMethod, String url,
                                      MultiValueMap<String, String> params,
                                      HttpHeader headers, Class<T> responseClassType) {
        RestHttpClient client = new RestHttpClient(httpMethod, url, params, headers);
        return this.send(client, responseClassType);
    }

    public <T> ResponseEntity<T> send(RestHttpClient client, Class<T> responseClassType) {
        if (client.getMethod().equals(HttpMethod.GET)) {
            UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(client.getUrl());
            if (client.getParams() != null) client.getParams().forEach(uriBuilder::queryParam);
            return restTemplate.getForEntity(uriBuilder.toUriString(), responseClassType);
        } else if (client.getMethod().equals(HttpMethod.POST)) {
            return restTemplate.postForEntity(client.getUrl(), client.getParams(), responseClassType);
        } else if (client.getMethod().equals(HttpMethod.PUT)) {
            return restTemplate.exchange(client.getUrl(), HttpMethod.PUT, client.toEntity(), responseClassType);
        } else if (client.getMethod().equals(HttpMethod.PATCH)) {
            restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
            return restTemplate.exchange(client.getUrl(), HttpMethod.PATCH, client.toEntity(), responseClassType);
        } else if (client.getMethod().equals(HttpMethod.DELETE)) {
            return restTemplate.exchange(client.getUrl(), HttpMethod.DELETE, client.toEntity(), responseClassType);
        } else {
            log.info("Not yet implement Method : {} ", client.getMethod());
            return null;
        }
    }
}

 


🚦샘플 소스

  • 샘플소스 Github 저장소 : https://github.com/rojae/RestTemplate-Demo
  • 사용한 테스트 API : https://jsonplaceholder.typicode.com/
  • Branch v1 : RestProvider 클래스에서 restTemplate을 new 키워드로 생성하여 통신한다. (스프링 Bean 관리 X)
  • Branch v2 : RestProvider 클래스에서 restTemplate을 bean으로 관리한다.
    (/test/RestTemplateTest.java 소스를 봐야한다)
 

GitHub - rojae/RestTemplate-Demo: Springboot RestTemplate Demo

Springboot RestTemplate Demo. Contribute to rojae/RestTemplate-Demo development by creating an account on GitHub.

github.com

 

JSONPlaceholder - Free Fake REST API

{JSON} Placeholder Free fake API for testing and prototyping. Powered by JSON Server + LowDB. Tested with XV. As of Oct 2021, serving ~1.7 billion requests each month.

jsonplaceholder.typicode.com

 

댓글