new URL("http://...")
openConnection()
URLConnection
getInputStream, getOutputStream
InputStream,OutputStream 처리
응답코드가 4xx 거나 5xx 면 IOException 이 터진다. (try catch 문으로 에러 처리 )
타임아웃 설정을 할 수 없다.
쿠키 제어가 불가하다.
try {
URL url = new URL(verifyUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", "Bearer "+apiKeyValue);
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
StringBuffer stringBuffer = new StringBuffer();
String inputLine;
while ((inputLine = bufferedReader.readLine()) != null) {
stringBuffer.append(inputLine);
}
response = stringBuffer.toString();
}
} catch (IOException e) {
System.out.printf("IOException Occured");
} finally {
if (connection != null) {
connection.disconnect();
}
}
return response;
스프링에서 제공하는 http 통신에 유용하게 쓸 수 있는 템플릿이며, HTTP 서버와의 통신을 단순화하고 RESTful 원칙을 지킨다. jdbcTemplate 처럼 RestTemplate 도 기계적이고 반복적인 코드들을 깔끔하게 정리해준다. 요청보내고 요청받는데 몇줄 안될 정도..
1. 어플리케이션이 RestTemplate를 생성하고, URI, HTTP메소드 등의 헤더를 담아 요청한다.
2. RestTemplate 는 HttpMessageConverter 를 사용하여 requestEntity 를 요청메세지로 변환한다.
3. RestTemplate 는 ClientHttpRequestFactory 로 부터 ClientHttpRequest 를 가져와서 요청을 보낸다.
4. ClientHttpRequest 는 요청메세지를 만들어 HTTP 프로토콜을 통해 서버와 통신한다.
5. RestTemplate 는 ResponseErrorHandler 로 오류를 확인하고 있다면 처리로직을 태운다.
6. ResponseErrorHandler 는 오류가 있다면 ClientHttpResponse 에서 응답데이터를 가져와서 처리한다.
7. RestTemplate 는 HttpMessageConverter 를 이용해서 응답메세지를 java object(Class responseType) 로 변환한다.
8.어플리케이션에 반환된다.
@RequestMapping("test")
@ResponseBody
public Map<String,Object> test(@RequestBody Map<String, Object> paramsMap, HttpServletRequest request) throws IOException {
Map<String,Object> response = new HashMap<>();
String url ="localhost:8080/test?name="+paramsMap.get("name").toString() +"&type="+ paramsMap.get("type").toString();
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set(secreKeyHeader,secreKeyValue);// ---> getForObject메서드는 헤더값을 설정할수 없다. 고로 getForObject -> exchanage() 사용할것.
HttpEntity<Map<String,Object>> requestEntity = new HttpEntity<>(headers);
ResponseEntity responseEntity = restTemplate.exchange(verifyUrl, HttpMethod.GET,requestEntity,Map.class);
Map<String,Object> content = (Map<String, Object>) responseEntity.getBody();
response = content;
System.out.println("content★★★★★★★★★★★★★★★★★★★★★★★"+content);
// RestTemplate 는 동기 방식으로 요청이 많아질 경우 요청스레드가 쌓여 서버가 다운될 수 있다.
// 그래서 pool관리 및 timeout 설정 등 커스터마이징 해야 함.
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); //HttpComponentsClientHttpRequestFactory 으로 timeout 설정은 가능하지만 connection 수를 제한 할수 없다.
// 하지만 import org.apache.http.impl.client.CloseableHttpClient 를 매개변수로 받을 수 있는 메서드를 제공ㄴ한다.
// HttpCilent 는 builder를 이용해 새로운 객체를 만들어서 위위 매개변수로 받을 수 있는 메서드 인자로 넣어주면서 추가적인 설정을 할 수 있다.
CloseableHttpClient httpClient = HttpClientBuilder.create()
.setMaxConnTotal(100)// 연결을 유지 할 최대 숫자
.setMaxConnPerRoute(50)// 특정경로당 최대 숫자
.build();
factory.setHttpClient(httpClient); // 동기실행에 사용될 httpClient 셋팅
factory.setReadTimeout(5000);// 읽기 시간초과 , ms
factory.setConnectTimeout(3000); // 연결시간 초과 ms
return response;
}
RestTemplate는 connection pool을 사용하지 않는 동기방식이다. 그래서 연결할때마다 로컬 포트를 열고 tcp connection을 맺는다.
이때 문제 갑자기 많은 요청이 들어오게 되면 요청한 서버에 응답을 늦게 줄때, 서버의 thread도 급격이 증가하여 이는 서버의 전체적인 장애로 연결된다. 이러한 문제를 차단하기 위해 connection수를 제한해야한다.
RestTemplate에는 내부적으로 사용되는 HttpClient의해 connection pool을 제한 할 수 있다.
Spring에서 HttpComponentsClientHttpRequestFactory를 제공한다.
이것을 이용해 timeout등을 설정 할 수 있다. 하지만 HttpComponentsClientHttpRequestFactory에는 connection의 수를 제한 할 수 있는 것이 없다.
하지만,
HttpComponentsClientHttpRequestFactory에는 connection 대신에 import org.apache.http.impl.client.CloseableHttpClient
를 매개변수로 받을 수 있는 method를 제공한다.
HttpClient는 Bulider을 이용해 새로운 객체를 만들어서 위의 매개변수로 받을 수 있는 메서드 인자로 넣어주면 추가적인 설정을 할 수 있다.
connection pool을 적용하기 위한 HttpClientBuilder를 사용하기 위해서는 dependency 라이브러리가 필요하다.
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient-osgi</artifactId>
<version>4.5.14</version>
</dependency>
CloseableHttpClient httpClient = HttpClientBuilder.create()
.setMaxConnTotal(100)// 연결을 유지 할 최대 숫자
.setMaxConnPerRoute(50)// 특정경로당 최대 숫자
.build();
factory.setHttpClient(httpClient); // 동기실행에 사용될 httpClient 셋팅
factory.setReadTimeout(5000);// 읽기 시간초과 , ms
factory.setConnectTimeout(3000); // 연결시간 초과 ms
return response;
GET request for "...." resulted in 200 (OK)
외부 api 호출 성공
참고자료]
https://exponential-e.tistory.com/50
https://junghyungil.tistory.com/84
spring doc
HTTP 기본 인증(Basic Authentication)