Server(java)에서 다른 Server의 서비스를 요청하는 Client로 쓸 수 있음
1. Client 종류
1. HttpURLConnection
- JDK에 포함
- java.net 패키지
- 핵심 API만 지원
- 개발 생산성이 떨어지나 속도는 좋음
2. HttpClient
- Apache에서 제공
- HttpURLConnection 보다 속도가 느림
- 에러가 존재함
3. RestTemplate
- Spring 에서 제공
- 코드의 복잡성을 줄이고 생산성 높임
- boot5 버전 까지만 사용, 이후로 deprecated 되었음
- 다음 버전에서는 사라질 전망
4. WebClient
- boot 5 이상에서는 WebClient를 사용할 것을 권장
- RestTemplate을 대체
5. 그외
- OKHttp, Retrofit...
2. RestTemplate 사용
1. RestTemplate 객체 생성
RestTemplate restTemplate = new RestTemplate();
2. Header 생성
HttpHeaders headers = new HttpHeaders();
// header : key:value
a. headers.add("key", "value");
b. headers.set헤더명("값");
c. headers.addAll(MultiValueMap<K, V>);
new HttpHeaders(MultiValueMap<K, V>)
3. Parameter 생성
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("key", "value");
4. 2,3을 포함한 요청 객체 생성
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String,String>>(params, headers);
5. 요청 전송 결과 처리
1) ResponseEntity
ResponseEntity<T> response = restTemplate.요청메서드명ForEntity(URI, request, T.class);
T t = response.getBody();
2) 응답을 원하는 Object
T t = restTemrestTemplate.요청메서드명ForObject(URI, request, T.class);
a. POST
ResponseEntity<T> response = restTemplate.postForEntity(URI, request, T.class);
T t = restTemplate.postForObject(URI, request, T.class);
b. GET
ResponseEntity<T> response = restTemplate.getForEntity(URI, T.class, request);
T t = restTemplate.getForObject(URI, T.class, request);
c. put, delete : ForXXX 없이 사용. put(), delete()
d. patch : patchForEntity가 없음, patchForObject() 만 있음
e. exchange
: 위의 것 모두 통합
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<T> res = restTemplate.exchange(
url, : URL 주소
HttpMethod.GET : 메서드 형식
req, : 요청 객체(header, parameter)
T.class : 결과 타입
)
if(res.getStatusCode()==HttpStatus.OK){
-- Request Success
T t = res.getBody()
}else {
-- Request Fail
}
* 응답의 결과가 여러 개 일 때
List<T> lists = restTemplate.getForObject("URL", List.class, request);
3. WebClient
1. API 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
2. 요청 사용법
A. WebClient 객체 생성
1. create()
WebClient webClient = WebClient.create();
WebClient webClient = WebClient.create("URI 주소");
2. builder()
WebClient webClient = WebClient.builder()
.baseUrl("")
.defaultHeader("Key", "value")
.defaultCookie("key", "value")
.build();
a. baseUrl : 기본 공통 URI 설정
b. defaultHeader : 공통 Header 설정
c. defaultCookie : 공통 Cookie 설정
d. filter : 요청에 사용할 클라이언트 필터
e. exchangeStrategies : HTTP 메시지 read, write 커스텀 할 때 사용
f. clientConnector : HTTP 클라이언트 라이브러리 설정
g. uriBuilderFactory : Base URL을 커스텀한 uriBuilderFactory
B. 요청 정보 설정
webClient.요청메서드명()
.uri("baseURL이후 URI", 파라미터설정)
.header("k", "v")
.cookie("k", "v");
C. Parameter 설정
a. Get 요청
1) uri("/list?page=1")
2) uri("/list?page={page}&kind={kind}", 1, "Title")
3) uri("/list", Map<String, Object> map)
Map<String, Object> map = new HashMap<>();
map.put("page", 1);
map.put("kind", "title");
uri("/list", map)
4) uri("/list", TestVO)
PostVO postVO = new PostVO();
postVO.setId("1");
uri("/list", postVO)
5) URIBuilder의 queryparam : <https://www.baeldung.com/webflux-webclient-parameters> 참조
b. Post 요청
1) bodyValue(PostVO)
2) body(Mono.just(PostVO), PostVO.class)
3) body(BodyInserters.fromFormData(multiValueMap))
4) body(BodyInserters.fromObject(postVO))
3. 응답
응답은 두가지 메서드 중에서 하나를 선택해서 처리
1. retrieve() : body를 받아 디코딩하는 간단한 메서드
2. exchange() : Client Response를 상태값 과 Header를 함께 가져오는 메서드
- exchange를 통해서 세세한 컨트롤이 가능하지만,
모든 처리를 직접 해야 하므로 메모리 누수 가능성이 있기 때문에 retrieve()권장
retrieve()는 크게 두가지의 객체 타입을 결과로 받음
1. toEntity()
status, headers, body을 포함하는 ResponseEntity 타입으로 받을 수 있음
WebClient webClient = WebClient.builder()
.baseUrl("<https://jsonplaceholder.typicode.com/>")
.build();
Mono<ResponseEntity<PostVO>> res = webClient.get()
.uri("posts/1")
.retrieve()
.toEntity(PostVO.class);
PostVO postVO = res.block().getBody();
2. bodyToMono(), bodyToFlux()
body의 데이터만 받고 싶을 때
toMono : 0-1개의 결과를 처리하는 객체
toFlux : 0-N개의 결과를 처리하는 객체
a. bodyToMono() : 결과가 0, 1개
WebClient webClient = WebClient.builder()
.baseUrl("<https://jsonplaceholder.typicode.com/>")
.build();
Mono<PostVO> res = webClient.get()
.uri("posts/2")
.retrieve()
.bodyToMono(PostVO.class);
PostVO postVO = res.block();
b. bodyToFlux : 결과가 0, N 개
WebClient webClient = WebClient.builder()
.baseUrl("<https://jsonplaceholder.typicode.com/>")
.build();
Flux<PostVO> res = webClient.get()
.uri("posts")
.retrieve()
.bodyToFlux(PostVO.class);
PostVO postVO = res.blockFirst();
res.subscribe((s)->{
PostVO pvo = s;
log.info("ID : {} ", s.getId());
});