본문 바로가기
내일배움캠프(Sparta)/Spring

[Spring] RestTemplate

by mmm- 2023. 11. 10.

1) RestTemplate

: 서버에서 다른 서버로 간편하게 요청할 수 있도록 스프링에서 제공하는 기능


RestTemplate의 Get 요청 방법

client 입장 서버

  1. RestTemplate 주입 받기
    • RestTemplateBuilder의 build() 메서드를 사용해 주입 받음.
  2. 요청 받은 검색어를 Query String 방식으로 Server 입장의 서버로 RestTemplate를 사용해 요청
    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();
    }​

    • UriComponentsBuilder를 사용해 URI class 객체를 쉽게 만들 수 있음.
    • getForEntity는 특정 URI로 GET 요청을 보내고, 응답 데이터를 지정한 클래스 타입(두번째 파라미터)의 객체로 자동변환해줌.
    • getForEntity를 통해 받는 것의 타입을 ResponseEntity 타입으로 받을 수 있음.
    • responseEntity.getBody()를 사용해 두 번째 파라미터로 전달한 클래스 타입으로 자동 변환된 객체를 가져올 수 있음.

 

server 입장 서버

public Item getCallObject(String query) {
    for (Item item : itemList) {
        if(item.getTitle().equals(query)) {
            return item;
        }
    }
    return null;
}
  1. server 입장의 서버에서 itemList를 조회하여 요청받은 검색어에 맞는 Item을 반환

요청한 Item이 여러 개일 경우

client 입장 서버

build.gradle 에 아래 내용 추가. (json 라이브러리 사용하기 위해)

// json
implementation 'org.json:json:20230227'

 

  1. 요청 URL을 만듦.
  2. 중첩 JSON 형태로 넘어올 경우, String 타입으로 한 번에 데이터를 받아 변환
  3. JSONObject 라이브러리의 JSONArray를 사용해 String으로 되어있는 중첩 JSON 조작.
  4. 조작하여 변환 후 ItemDto 타입의 리스트로 만들어 반환
  5. ItemDto에 받아온 JSONObject를 사용해 초기화하는 생성자 추가
    @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");
        }
    }​​

server 입장 서버

  1. server 입장의 서버에서 itemList를 ItemResponseDto에 담아 반환
    public ItemResponseDto getCallList() {
        ItemResponseDto responseDto = new ItemResponseDto();
        for (Item item : itemList) {
            responseDto.setItems(item);
        }
        return responseDto;
    }​

RestTemplate의 Post 요청 방법

client 입장 서버

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();
}
  1. 요청 받은 검색어를 PathVariable 방식으로 Server 입장의 서버로 RestTemplate를 사용하여 요청
    • .expand()한 후 .path에서 중괄호에 들어갈 값을 넣어주면 됨.
    • Get과는 다르게 Post방식에서는 Body 부분에 데이터를 넘길 수 있기 때문에 RestTemplate에서는 postForEntity를 가지고 있음. (postForEntity => post 방식일 때 사용하는 메서드)
      • 첫번째 인자로는 uri, 두번째인자로는 httpBody에 넣어줄 데이터를, 세번째 인자로 전달받은 데이터랑 mapping 할 거.
      • 두번째 인자는 객체를 넣어주면 RestTemplate이 자동으로 변환해줌.

 

server 입장 서버

@PostMapping("/post-call/{query}")
    public Item postCall(@PathVariable String query, @RequestBody UserRequestDto requestDto) {
        return itemService.postCall(query, requestDto);
    }
  1. Server 입장의 서버에서 itemList를 조회하여 요청 받은 Item을 반환

RestTemplate의 exchange

RestTemplate으로 요청을 보낼 때 Header에 특정 정보를 같이 전달하고 싶다면?

client입장 서버

    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());
    }
  1. RestTemplate의 exchange 메서드 사용
    (이전에는 getForEntity나 postForEntity를 사용해 get, post 를 지정하였었음.)
    • 첫번째 인자로 RequestEntity 타입의 필드를 줌
      (uri, header, body의 정보를 http에 넣어 한 번에 전달 가능.)
      • header에 첫번째로 X-Authorization을 키로 주고, 두번째로는 받아온 토큰 넣어줌.
    • 두번째는 받아올 데이터를 String 타입으로 받아옴.

 

server 입장 서버

@PostMapping("/exchange-call")
public ItemResponseDto exchangeCall(@RequestHeader("X-Authorization") String token, @RequestBody UserRequestDto requestDto) {
    return itemService.exchangeCall(token, requestDto);
}
  1. header에서 키가 X-Authorization인 값(토큰)을 받고, 클라이언트 서버에서 httpBody 쪽에 넣어준 userData를 가져오기 위해 @RequestBody annotation, UseRequestDto를 사용해 그 데이터를 받아와 파라미터로 넣어준 후 서비스쪽으로 보냄.
  2. 전달된 header와 body의 정보를 확인할 수 있음.
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();
}

용어 정리

  • UriComponentsBuilder
    : URI를 쉽게 생성하게 돕는 도구
  • ResponseEntity
    : HTTP 관련된 데이터에 응답할 때 사용하는 클래스.

'내일배움캠프(Sparta) > Spring' 카테고리의 다른 글

[Spring] Entity 클래스 간의 관계  (0) 2023.11.20
[Spring] Entity 연관관계  (1) 2023.11.14
[Spring] Spring Security / Validation  (1) 2023.11.09
[Spring] Filter  (0) 2023.11.09
[Spring] JWT / 패스워드 암호화  (0) 2023.11.08