-
[Spring] RestTemplate을 편리하게 사용하자 (샘플 포함)백엔드/Spring 2022. 6. 12. 19:19
🚀 들어가면서
- 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
반응형'백엔드 > Spring' 카테고리의 다른 글
[Spring] Springboot Properties 설정파일을 외부에서 가져오자 (0) 2022.08.11 JPA Entity 생성시 Table Character set - UTF8 미설정 이슈 (0) 2022.08.11 [Spring] 인텔리제이에서 Mybatis Generator 사용하는 법 (0) 2022.06.12 [Spring] Mybatis, JPA, ORM에 대해서 간단하게 알아보자 (2) 2022.05.21