🚀 들어가면서
- 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;
}
}
}
🚦샘플 소스