지금까지는 클라이언트(브라우저)로부터 요청을 받는 서버의 입장에서 개발을 진행해왔다.
하지만 어떤 경우에는 서버가 Client의 입장이 되어야 할때도 있다.
예를 들어 카카오에서 만든 주소 검색 API를 사용해야한다면 Kakao 서버에 요청을 보내야한다.
따라서 Spring에서는 서버에서 다른 서버로 간편하게 요청할 수 있도록 RestTemplate 기능을 제공하고 있다.
RestTemplate는 spring-boot-starter-web 모듈에 포함돼 있는 기능으로 별도의 의존성을 추가할 필요 없다.
프로젝트 2개를 만들어서 Client 입장의 서버는 8080포트(기본값), Server 입장의 서버는 7070포트(등 다른 포트)로 설정 후 동시에 실행시켜 확인해볼 수 있다.
private final RestTemplate restTemplate; // DI 안됨
public RestTemplateService(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
restTemplate.getForEntity(uri, ItemDto.class);
: Get 방식으로 해당 URI의 서버에 요청을 진행response.getBody()
: 두 번째 파라미터로 전달한 클래스 타입으로 자동 변환된 객체 반환public ItemDto getCallObject(String query) {
// 요청 URL 만들기
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070")
.path("/api/server/get-call-obj")
.queryParam("query", query)
.encode()
.build()
.toUri();
log.info("uri = " + uri);
ResponseEntity<ItemDto> responseEntity = restTemplate.getForEntity(uri, ItemDto.class);
log.info("statusCode = " + responseEntity.getStatusCode());
return responseEntity.getBody();
}
public List<ItemDto> getCallList() {
// 요청 URL 만들기
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070")
.path("/api/server/get-call-list")
.encode()
.build()
.toUri();
log.info("uri = " + uri);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
log.info("statusCode = " + responseEntity.getStatusCode());
log.info("Body = " + responseEntity.getBody());
return fromJSONtoItems(responseEntity.getBody());
}
implementation 'org.json:json:20230227'
public List<ItemDto> fromJSONtoItems(String responseEntity) {
JSONObject jsonObject = new JSONObject(responseEntity);
JSONArray items = jsonObject.getJSONArray("items");
List<ItemDto> itemDtoList = new ArrayList<>();
for (Object item : items) {
ItemDto itemDto = new ItemDto((JSONObject) item);
itemDtoList.add(itemDto);
}
return itemDtoList;
}
@Getter
@NoArgsConstructor
public class ItemDto {
private String title;
private int price;
public ItemDto(JSONObject itemJson) {
this.title = itemJson.getString("title");
this.price = itemJson.getInt("price");
}
}
public Item getCallObject(String query) {
for (Item item : itemList) {
if(item.getTitle().equals(query)) {
return item;
}
}
return null;
}
public ItemResponseDto getCallList() {
ItemResponseDto responseDto = new ItemResponseDto();
for (Item item : itemList) {
responseDto.setItems(item);
}
return responseDto;
}
restTemplate.postForEntity(uri, user, ItemDto.class);
: Post 방식으로 해당 URI의 서버에 요청을 진행public ItemDto postCall(String query) {
// 요청 URL 만들기
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070")
.path("/api/server/post-call/{query}")
.encode()
.build()
.expand(query)
.toUri();
log.info("uri = " + uri);
User user = new User("Robbie", "1234");
ResponseEntity<ItemDto> responseEntity = restTemplate.postForEntity(uri, user, ItemDto.class);
log.info("statusCode = " + responseEntity.getStatusCode());
return responseEntity.getBody();
}
itemList를 조회하여 요청받은 검색어에 맞는 Item 반환
public Item postCall(String query, UserRequestDto userRequestDto) {
System.out.println("userRequestDto.getUsername() = " + userRequestDto.getUsername());
System.out.println("userRequestDto.getPassword() = " + userRequestDto.getPassword());
return getCallObject(query);
}
restTemplate.exchange(requestEntity, String.class);
: RequestEntity를 사용해 서버에 요청을 진행public List<ItemDto> exchangeCall(String token) {
// 요청 URL 만들기
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:7070")
.path("/api/server/exchange-call")
.encode()
.build()
.toUri();
log.info("uri = " + uri);
User user = new User("Robbie", "1234");
RequestEntity<User> requestEntity = RequestEntity
.post(uri)
.header("X-Authorization", token)
.body(user);
ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
return fromJSONtoItems(responseEntity.getBody());
}
@RequestHeader("X-Authorization")
: 헤더에서 주어진 key값을 반환@PostMapping("/exchange-call")
public ItemResponseDto exchangeCall(@RequestHeader("X-Authorization") String token, @RequestBody UserRequestDto requestDto) {
return itemService.exchangeCall(token, requestDto);
}
public ItemResponseDto exchangeCall(String token, UserRequestDto requestDto) {
System.out.println("token = " + token);
System.out.println("requestDto.getUsername() = " + requestDto.getUsername());
System.out.println("requestDto.getPassword() = " + requestDto.getPassword());
return getCallList();
}