스프링에서 rest api call 하기 / spring 에서 rest call / spring 에서 http request
RestTemplate
Spring framework 에서 Rest API 호출을 위해 RestTemplate 이라는 것을 제공한다. ref. 2, ref. 3 에서 간단한 예제를 확인할 수 있다.
postForObject
Server 에서 RESTful API server 에 request 를 POST 방식으로 form 의 data 는 json 형식으로 보낼 때 방법. ElasticSearch 등을 사용할 때 활용할 수 있다. 혹시나 해서 적어놓는데, ElasticSearch 는 Java API 를 따로 제공한다.(참고)
@Override public JsonResult retrieve() { String JSONInput = ("{\n" + " \"aggs\": {\n" + " \"aggs_stats\" : {\n" + " \"date_histogram\":{\n" + " \"field\" : \"event_timestamp\",\n" + " \"interval\" : \"hour\"\n" + " }\n" + " }\n" + " }\n" + "} "); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity param= new HttpEntity(JSONInput, headers); RestTemplate restTemplate = new RestTemplate(); String result = restTemplate.postForObject(url, param, String.class); return new ElasticSearchResult(result); }
setMessageConverters
ref. 5, ref. 6 을 통해서 MessageConverters 를 설정해서 postForObject 를 이용하는 방법을 알아볼 수 있다.
// RestTemplate 에 MessageConverter 세팅 List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>(); converters.add(new FormHttpMessageConverter()); converters.add(new StringHttpMessageConverter()); RestTemplate restTemplate = new RestTemplate(); restTemplate.setMessageConverters(converters); // parameter 세팅 MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>(); map.add("name", "xx"); map.add("password", "xx"); // post String result = rest.postForObject("http://localhost:8080/soa-server/user/", map, String.class); System.out.println(result);
getForObject 의 한계
Accept 를 따로 정해주지 않는 경우에 RestTemplate#getForObject 에서는 기본적으로 아래 header 를 이용한다.
Accept : application/json, application/*+json
그래서 getForObject 를 이용해서 만약에 다른 Accept 를 사용하고 싶다면, 다른 함수를 이용해야 한다.(execute, exchange)
getForObject 에서 param 을 주는 방법
ref. 4 를 참고하자. 대략 아래와 같은 방식을 이용한다.
UriComponentsBuilder urlWithoutParam = UriComponentsBuilder.fromUriString("http://dd.net") .path("/path1/ddd"); for(Map.Entry<String, Object> e: param.entrySet()){ urlWithoutParam = urlWithoutParam.queryParam(e.getKey(), e.getValue()); } URI reqUrl = urlWithoutParam.build().toUri(); RestTemplate restTemplate = new RestTemplate(); return restTemplate.getForObject(reqUrl, String.class);
RestTemplate#execute
좀 더 자유로운 Http request 를 위해서 execute 를 사용하게 되었다. 그리고 이 RestTemplate 의 doExecute 에서 Extractor 를 사용하기 때문에 이 녀석만 제대로 맞춰 주면 된다.
protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor) throws RestClientException { try { ClientHttpRequest request = createRequest(url, method); if (requestCallback != null) { requestCallback.doWithRequest(request); } response = request.execute(); if (!getErrorHandler().hasError(response)) { logResponseStatus(method, url, response); } else { handleResponseError(method, url, response); } if (responseExtractor != null) { return responseExtractor.extractData(response); }
Example
// ApiCallResponseExtractor.java public class ApiCallResponseExtractor extends HttpMessageConverterExtractor<String> { public ApiCallResponseExtractor (Class<String> responseType, List<HttpMessageConverter<?>> messageConverters) { super(responseType, messageConverters); } @Override public String extractData(ClientHttpResponse response) throws IOException { String result; if (response.getStatusCode() == HttpStatus.OK) { Scanner scanner = new java.util.Scanner(response.getBody()).useDelimiter("[\\(\\)]"); scanner.next(); // callback name, String json = scanner.next(); result = json; } else { result = null; } return result; } }
// MyController.java final String url = "http://10.10.2.100:8080/portal/customer/getCustomerList?" + JsonKey.CALLBACK + "={" + JsonKey.CALLBACK + "}" + "&" + JsonKey.USER_ID + "={" + JsonKey.USER_ID + "}"; Map<String, String> vars = new HashMap<String, String>(); vars.put(JsonKey.CALLBACK, JsonKey.API_CALLBACK_NAME); vars.put(JsonKey.USER_ID, "test_id"); RestTemplate restTemplate = new RestTemplate(); ResponseExtractor<String> responseExtractor = new ApiCallResponseExtractor(String.class, restTemplate.getMessageConverters()); String response = restTemplate.execute(url, HttpMethod.GET, null, responseExtractor, vars);
Header field Accept
참고로 execute 를 사용하면 기본 Accept 는 아래를 사용하게 된다.
Accept : text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
RestTemplate 을 이용해서 json request
ref. 7 에 잘 나와 있다.
Reference
- RestTemplate (Spring Framework 4.1.3.RELEASE API)
- http://spring.io/guides/gs/consuming-rest/#initial
- http://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplate
- android - How to send a getForObject request with parameters Spring MVC - Stack Overflow
- java - Spring RestTemplate postForObject with Header: webservice can't find my header parameters - Stack Overflow
- Sending POST parameters with RestTemplate requests - Spring Forum
- Rest Template Json Request | Spring Tutorials
'Tech develop > Spring' 카테고리의 다른 글
[Spring Boot] json response할 때 Enum 객체 전체 보여주기 (0) | 2021.01.11 |
---|---|
[Swagger]OpenAPI 3.0을 이용한 Spring REST API 문서화 (0) | 2021.01.11 |
[Spring/JAVA] 자바 http url 호출 예제(HttpURLConnection 이용) (0) | 2017.02.14 |