Github: RestApiService
Playground/src/main/java/com/example/playground/spring/restapi at master · HSRyuuu/Playground
Contribute to HSRyuuu/Playground development by creating an account on GitHub.
github.com
이 코드는 Lombok에 의존합니다. 참고하세요.
사용법
RestApiService restApiService = new RestApiService();
// 1. url
String url = "https://jsonplaceholder.typicode.com/comments";
// 2. query parameters
QueryParams queryParams = new QueryParams()
.add("postId", "1")
.add("page", "2");
// 3. Http Headers
ExtraHeaders headers = new ExtraHeaders()
.add("Content-Type", "application/json")
.add("access_token", "test-123-123");
// 4. Request Body
PostAddDto postUpdateDto = new PostAddDto(); // some-object
// 5. execute
ApiResponse response = restApiService.post(url, queryParams, headers, postUpdateDto);
1. url
base url을 세팅해줍니다.
물론 이 url에 query parameters까지 모두 포함시켜도 됩니다.
ex) https://jsonplaceholder.typicode.com/comments?postId=1&page=2
2. QueryParams
Map<String, String>을 감싸고 있습니다.
query parameter 들을 key - value 형태로 추가할 수 있습니다.
add와 동시에 validation이 되어 잘못된 값은 무시합니다.
3. ExtraHeaders
Map<String, String>을 감싸고 있습니다.
Http Header에 추가할 값들을 key - value 형태로 추가할 수 있습니다.
마찬가지로, add와 동시에 validation이 되어 잘못된 값은 무시합니다.
4. Request Body
HttpRequest Body에 해당하는 객체를 넣습니다.
GET, DELETE의 경우에도 사용은 가능하게 해 뒀습니다.
5. 실행
RestApiService는 get(), post(), put(), delete() 메서드를 지원합니다.
여러 가지 상황으로 오버로딩 되어있고, 없다면 매개변수를 넣고, 사용하지 않는 매개변수는 null로 대입하여 사용할 수 있습니다.
소스코드
class RestApiService
@Slf4j
public class RestApiService {
private final RestTemplate restTemplate = new RestTemplate();
/**
* execute HTTP GET Request
*
* @param url : base url
* @param queryParams : query parameters
* @param extraHeaders : Http Headers
* @param data : Http Body (optional)
* @return ApiResponse(status, body, errorMessage)
*/
public ApiResponse get(String url, QueryParams queryParams, ExtraHeaders extraHeaders, Object data) {
return this.getResult(HttpMethod.GET, url, queryParams, extraHeaders, data);
}
public ApiResponse get(String url) {
return this.get(url, null, null, null);
}
public ApiResponse get(String url, ExtraHeaders extraHeaders) {
return this.get(url, null, extraHeaders, null);
}
// POST
public ApiResponse post(String url, QueryParams queryParams, ExtraHeaders extraHeaders, Object data) {
return this.getResult(HttpMethod.POST, url, queryParams, extraHeaders, data);
}
public ApiResponse post(String url, Object body) {
return this.post(url, null, null, body);
}
public ApiResponse post(String url, ExtraHeaders extraHeaders, Object body) {
return this.post(url, null, extraHeaders, body);
}
// PUT
public ApiResponse put(String url, QueryParams queryParams, ExtraHeaders extraHeaders, Object data) {
return this.getResult(HttpMethod.PUT, url, queryParams, extraHeaders, data);
}
public ApiResponse put(String url, Object body) {
return this.put(url, null, null, body);
}
public ApiResponse put(String url, ExtraHeaders extraHeaders, Object body) {
return this.put(url, null, extraHeaders, body);
}
// DELETE
public ApiResponse delete(String url, QueryParams queryParams, ExtraHeaders extraHeaders, Object data) {
return this.getResult(HttpMethod.DELETE, url, queryParams, extraHeaders, data);
}
public ApiResponse delete(String url, Object body) {
return this.delete(url, null, null, null);
}
public ApiResponse delete(String url, ExtraHeaders extraHeaders) {
return this.delete(url, null, extraHeaders, null);
}
/**
* HTTP Request
*
* @param httpMethod GET / POST / PUT / DELETE
* @param baseUrl Request URL
* @param queryParameters query parameter map
* @param extraHeaders http header map
* @param body Request Body
* @return ApiResponse(status, body, errorMessage)
*/
private ApiResponse getResult(HttpMethod httpMethod,
String baseUrl,
QueryParams queryParameters,
ExtraHeaders extraHeaders,
Object body) {
//baseUrl validation
if (baseUrl == null || baseUrl.isEmpty()) {
throw new IllegalArgumentException("Base URL cannot be null or empty value");
}
try {
String url = RestApiUtils.buildFullUrl(baseUrl, queryParameters);
HttpHeaders headers = RestApiUtils.generateHttpHeaders(extraHeaders);
log.info("[{}] API Request: URL=[{}], Headers=[{}], Body=[{}]", httpMethod, url, headers, body);
long startTime = System.currentTimeMillis();
HttpEntity<Object> request = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.exchange(url, httpMethod, request, String.class);
log.info("[{}] API Response: Status=[{}], TimeElapsed={}ms, Body=[{}]",
httpMethod, response.getStatusCode(), System.currentTimeMillis() - startTime, response.getBody());
return new ApiResponse(response.getStatusCode(), null, response.getBody());
} catch (HttpClientErrorException | HttpServerErrorException e) {
return new ApiResponse(e.getStatusCode(), e.getResponseBodyAsString(), e.getMessage());
} catch (RestClientException e) {
return new ApiResponse(HttpStatus.INTERNAL_SERVER_ERROR, null, e.getMessage());
} catch (Exception e) {
return ApiResponse.unexpectedError();
}
}
}
class QueryParams
/**
* Http Request Url 에 포함될 query parameter 값들을 감싼 클래스
* <br> - 설계시, Map data 에는 잘못된 값이 들어갈 수 없도록 한다.
*/
@ToString
@Getter
public class QueryParams {
private Map<String, String> data;
public QueryParams() {
this.data = new HashMap<>();
}
public QueryParams(Map<String, String> data) {
if(data == null){
this.data = new HashMap<>();
return;
}
for(Map.Entry<String, String> entry : data.entrySet()){
this.add(entry.getKey(), entry.getValue());
}
}
public QueryParams add(String key, String value) {
if(!RestApiUtils.validateKeyValue(key, value)){
return this;
}
this.data.put(key, value);
return this;
}
public String getQueryParameterString(){
return "";
}
}
class ExtraHeaders
/**
* Http Request Header 에 포함될 값들을 감싼 클래스
* <br> - 설계시, Map data 에는 잘못된 값이 들어갈 수 없도록 한다.
*/
@ToString
@Getter
public class ExtraHeaders {
Map<String, String> data;
public ExtraHeaders() {
this.data = new HashMap<>();
}
public ExtraHeaders(Map<String, String> data) {
if(data == null){
this.data = new HashMap<>();
return;
}
for(Map.Entry<String, String> entry : data.entrySet()){
this.add(entry.getKey(), entry.getValue());
}
}
public ExtraHeaders add(String key, String value){
if(!RestApiUtils.validateKeyValue(key, value)){
return this;
}
this.data.put(key, value);
return this;
}
}
class ApiResponse
@ToString
@Getter
@Setter
@AllArgsConstructor
public class ApiResponse {
private HttpStatus status;
private String errorMessage;
private Object body;
public static ApiResponse unexpectedError(){
return new ApiResponse(HttpStatus.INTERNAL_SERVER_ERROR, "unexpected error",null);
}
}
class RestApiUtils
public class RestApiUtils {
/**
* HTTP Header 객체 생성
* @param extraHeaders ExtraHeaders Object
* @return
*/
public static HttpHeaders generateHttpHeaders(ExtraHeaders extraHeaders) {
if (extraHeaders == null || extraHeaders.getData() == null || extraHeaders.getData().isEmpty()) {
return new HttpHeaders();
}
HttpHeaders headers = new HttpHeaders();
for (Map.Entry<String, String> entry : extraHeaders.getData().entrySet()) {
headers.add(entry.getKey(), entry.getValue());
}
return headers;
}
/**
* 전체 URL 생성 (base url + query params)
* @param queryParams QueryParams Object
* @return full url with query parameters
*/
public static String buildFullUrl(String baseUrl, QueryParams queryParams){
if(baseUrl == null || baseUrl.isEmpty()){
throw new IllegalArgumentException("Base Url must not be null or empty");
}
if(queryParams == null || queryParams.getData() == null || queryParams.getData().isEmpty()){
return baseUrl;
}
//make queryParameter String
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> entry : queryParams.getData().entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}
String queryParameterString = builder.build().toString();
if(baseUrl.contains("?")){
return baseUrl + queryParameterString.replaceAll("\\?", "&");
}
return baseUrl + queryParameterString;
}
/**
* key, value String validation
* @param key Map key
* @param value Map value
* @return Boolean result
*/
public static boolean validateKeyValue(String key, String value){
if(key == null || key.isEmpty()){
return false;
}
if( value == null || value.isEmpty()) {
return false;
}
return true;
}
}
'[ 기타 ] > 오픈소스 라이브러리' 카테고리의 다른 글
[SonarQube] 오픈소스 정적분석 Tool 소나큐브 사용법 (0) | 2024.09.19 |
---|---|
[java/Playground] Apache POI 엑셀 파일 다루기 (0) | 2024.09.04 |
[Apache POI] Java 코드로 엑셀(.xlsx) 파일 생성하기 - Java로 Excel 다루기 (0) | 2024.07.18 |
[SchemaSpy] DB 스키마 분석, 시각화 Tool 사용 방법 (1) | 2024.07.02 |