Everyday Dev System

RestTemplate - get방식 : Client 서버 코드 설명 본문

내배캠 주요 학습/Spring 숙련

RestTemplate - get방식 : Client 서버 코드 설명

chaeyoung- 2023. 6. 20. 14:17

https://github.com/Chaeyounglim/spring-resttemplate-server

https://github.com/Chaeyounglim/spring-resttemplate-client1

 

@Slf4j
log를 찍기 위해서는 해당 클래스 위에 해당 어노테이션을 기재해야 한다.


클라이언트 입장의 서버 프로젝트 생성
- web,lombok 선택
- 8081

서버 프로젝트 생성
- web,lombok 선택
- 7071
Client 서버 8081
Server 서버 7071
build.gradle에 의존성 추가
// json
implementation 'org.json:json:20230227'

 

client project

더보기

[controller] - ItemController.java

package com.sparta.springresttemplateserver.controller;

import com.sparta.springresttemplateserver.dto.ItemResponseDto;
import com.sparta.springresttemplateserver.dto.UserRequestDto;
import com.sparta.springresttemplateserver.entity.Item;
import com.sparta.springresttemplateserver.service.ItemService;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/server")
public class ItemController {

    private final ItemService itemService;

    public ItemController(ItemService itemService) {
        this.itemService = itemService;
    }

    @GetMapping("/get-call-obj")
    public Item getCallObject(@RequestParam String query) {
        return itemService.getCallObject(query);
    }

    @GetMapping("/get-call-list")
    public ItemResponseDto getCallList() {
        return itemService.getCallList();
    }

    @PostMapping("/post-call/{query}")
    public Item postCall(@PathVariable String query, @RequestBody UserRequestDto requestDto) {
        return itemService.postCall(query, requestDto);
    }

    @PostMapping("/exchange-call")
    public ItemResponseDto exchangeCall(@RequestHeader("X-Authorization") String token, @RequestBody UserRequestDto requestDto) {
        return itemService.exchangeCall(token, requestDto);
    }
}

 

[dto] - ItemDto.java

package com.sparta.springresttemplateclient1.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;
import org.json.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");
    }
}

 

[entity] - User.java

package com.sparta.springresttemplateclient1.entity;
import lombok.Getter;

@Getter
public class User {
    private String username;
    private String password;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
}

 

[service] - RestTemplateService.java

package com.sparta.springresttemplateclient1.service;

import com.sparta.springresttemplateclient1.dto.ItemDto;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class RestTemplateService {

    private final RestTemplate restTemplate;

    public RestTemplateService(RestTemplateBuilder builder) {
        this.restTemplate = builder.build();
    }

    // String query에 맞는 데이터의 ItemDto 타입 반환하기
    public ItemDto getCallObject(String query) {
        // 요청 URL 만들기
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:7071")
                .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:7071")
                .path("/api/server/get-call-list")
                .encode()
                .build()
                .toUri();
        log.info("uri = " + uri);

        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
        // Json 형태가 복합적이므로 하나의 클래스로 받을 수 없으므로 String으로 받은 후에 Json으로 다시 변환할거임.

        log.info("statusCode = " + responseEntity.getStatusCode());
        log.info("Body = " + responseEntity.getBody());

        return fromJSONtoItems(responseEntity.getBody());
    }

    public ItemDto postCall(String query) {
        return null;
    }

    public List<ItemDto> exchangeCall(String token) {
        return null;
    }

/*    {
        "items":
        [
                {"title":"Mac","price":3888000},
                {"title":"iPad","price":1230000},
                {"title":"iPhone","price":1550000},
                {"title":"Watch","price":450000},
                {"title":"AirPods","price":350000}
        ]
    }*/

    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;
    }
}

 

 

Client Server의 역할

 

1. RestTemplate은 RestTemplate builder를 통해 등록해야 함.


자동으로 Bean 생성이 안되므로, RestTemplateBuilder 클래스 내에 build() 메서드를 통해 생성할 수 있다.

    public RestTemplateService(RestTemplateBuilder builder) {
        this.restTemplate = builder.build();
    }

 

 

2. 클라이언트에서 서버로 요청 보내기

 

1) URL 생성

    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7071")
            .path("/api/server/get-call-obj")
            .queryParam("query", query)
            .encode()
            .build()
            .toUri();

 

2) 요청을 보내고 Dto 타입으로 반환받기

ResponseEntity<ItemDto> responseEntity = restTemplate.getForEntity(uri, ItemDto.class);

restTemplate.getForEntity(uri, ItemDto.class); 

get 방식으로 해당 url 서버에 요청한다.

또한 해당 요청에 대한 수신으로 받는 데이터를 ItemDto 타입으로 받는다.

 

public ItemDto getCallObject(String query) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7071")
            .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();
}

-> String query에 맞는 데이터의 ItemDto 타입을 반환받아서 return 하는 메서드이다.

 

 

 

아래 메서드는 모든 데이터를 다 가져오는 메서드이다.

Json 형태가 하나가 아니므로 ItemDto와 같은 하나의 클래스로 받을 수 없다.

그러므로 String으로 받은 후에 Json으로 다시 변환할거임. 

 

이때 Json parsing을 위해 의존성을 추가해야 한다.

build.gradle에 의존성 추가
// json
implementation 'org.json:json:20230227'
    public List<ItemDto> getCallList() {
        // 요청 URL 만들기
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:7071")
                .path("/api/server/get-call-list")
                .encode()
                .build()
                .toUri();
        log.info("uri = " + uri);

        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
        // Json 형태가 복합적이므로 하나의 클래스로 받을 수 없으므로 String으로 받은 후에 Json으로 다시 변환할거임.

        log.info("statusCode = " + responseEntity.getStatusCode());
        log.info("Body = " + responseEntity.getBody());

        return fromJSONtoItems(responseEntity.getBody());
    }