🚀 들어가면서
- 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 |
댓글