ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] RestTemplate을 사용하여 json 요청
    카테고리 없음 2022. 7. 7. 15:13

    Server to Server http 통신에 사용되는 RestTemplate 

    public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {
    	//사용가능한 http메서지 컨버터들을 담기 위한 리스트
    	private final List<HttpMessageConverter<?>> messageConverters;
    public abstract class InterceptingHttpAccessor extends HttpAccessor {
    public abstract class HttpAccessor {

    RestTemplate 인스턴스 생성

     

    • Empty Constructor
     public RestTemplate() {

     

    기본으로 사용가능한 http 메세지 컨버터들을 리스트로 초기화 및 프로젝트에서 추가해놓은 gson, jackson이 존재하는지 체크후 존재하면 메세지 컨버터 리스트에 추가

     

    HttpAccessor 생성자에서 기본으로 사용될 http 요청 팩토리를 SimpleClientHttpRequestFactory로 설정


    • RestTemplate이 사용할 http 요청 팩토리를 지정하는 생성자
    public RestTemplate(ClientHttpRequestFactory requestFactory) {

    앞서 살펴본 this()를 통해 모든 셋팅을 완료한 뒤 this.setRequestFactory(requestFactory)를 통해 http 요청 팩토리만 교체


    • http 요청 팩토리로 HttpComponentsClientHttpRequestFactory를 사용할시 dependency 추가 필요
    <dependency>
    	<groupId>org.apache.httpcomponents</groupId>
    	<artifactId>httpclient</artifactId>
    	<version>4.5.2</version>
    </dependency>

    Http 헤더

     

     

    특정 Http헤더는 하나의 값이 아닌 여러 값을 가질 수 있다.(ex 받을 수 있는 언어 accept 한국어,일본어,영어등등)

    Map의 경우 특정 key에 하나의 값만 적용될 수 있기 때문에 Spring에서는 다음의 인터페이스와 구현 클래스를 제공

     

    헤더 모방 예제

     

    public class Program {
        public static void main(String[] args) {
            MultiValueMap<String, String> allHeader = new LinkedMultiValueMap<>();
    
            allHeader.add("받을 수 있는 컨텐트 타입", "제이슨");
            allHeader.add("받을 수 있는 컨텐트 타입", "이미지");
    
            allHeader.add("지원되는 언어", "영어");
            allHeader.add("지원되는 언어", "한국어");
        }
    }

    Http헤더사용을 위해 HttpHeaders클래스를 지원하며 MultiValueMap을 상속했다.

     

    헤더 추가시 하드 코딩시 발생할 수 있는 에러를 위해 HttpHeaders,MediaType의 상수를 사용하면 된다.

    import org.springframework.http.HttpHeaders;
    import org.springframework.http.MediaType;
    
    public class Program {
        public static void main(String[] args) {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            //headers.set("Content-Type", "application/json");와 같음
        }
    }

    http 메세지

    http 메세지는 헤더와 바디로 구성되어 있다. HttpEntity클래스는 http메세지에 해당

    HttpEntity생성시 타입변수를 지정해주면 해당 타입이 메세지 바디의 타입이 된다.

     

    http 요청 메세지는 HttpEntity를 상속한 RequestEntity클래스

     

    http 응답 메세지는 HttpEntity를 상속한 ResponseEntity클래스


    uri를 생성하기 위해 UriComponentsBuilder

    import org.springframework.util.LinkedMultiValueMap;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.util.UriComponents;
    import org.springframework.web.util.UriComponentsBuilder;
    
    public class Program {
        public static void main(String[] args) {
            MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
            queryParams.add("user", "kim");
            queryParams.add("age", "20");
    
            UriComponents uriComponents = UriComponentsBuilder.newInstance()
                    .scheme("http")
                    .host("localhost:8080")
                    .path("/test.do")
                    .queryParams(queryParams)
                    .build();
    //public UriComponentsBuilder queryParams(@Nullable MultiValueMap<String, String> params) {
            String url = uriComponents.toUriString();
            System.out.println(url);
        }
    }


     

    RestTemplate의 exchange메서드를 사용하여 json을 받아옴

     

    http://jsonplaceholder.typicode.com/todos

    에서 받은 json데이터를 받아보자

     

    JSON 스펙에 해당하는 클래스

    class Item {
        private int userId;
        private int id;
        private String title = "";
        private boolean completed;
    
        public Item() {
        }
    
        public int getUserId() {
            return userId;
        }
    
        public void setUserId(int userId) {
            this.userId = userId;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public boolean isCompleted() {
            return completed;
        }
    
        public void setCompleted(boolean completed) {
            this.completed = completed;
        }
    
        @Override
        public String toString() {
            return "Item{" +
                    "userId=" + userId +
                    ", id=" + id +
                    ", title='" + title + '\'' +
                    ", completed=" + completed +
                    '}';
        }
    }

     

    JSON요청

    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import com.google.gson.reflect.TypeToken;
    import org.springframework.http.*;
    import org.springframework.http.converter.StringHttpMessageConverter;
    import org.springframework.web.client.RestTemplate;
    import org.springframework.web.util.UriComponents;
    import org.springframework.web.util.UriComponentsBuilder;
    
    import java.nio.charset.StandardCharsets;
    import java.util.List;
    
    public class Program {
        public static void main(String[] args) {
    
            //인스턴스 생성시 기본으로 StringHttpMessageConverter가 포함된다.
            RestTemplate restTemplate = new RestTemplate();
    
            int index = -1;
            for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
                if (restTemplate.getMessageConverters().get(i) instanceof StringHttpMessageConverter) {
                    index = i;
                }
            }
            if (index == -1) {
                restTemplate.getMessageConverters().add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
            } else {
                System.out.println("restTemplate의 http메세지 컨버터 리스트 필드의 " + index + "번 아이템에 포함됨");
                System.out.println("utf-8인것으로 StringHttpMessageConverter로 교체");
                System.out.println();
                restTemplate.getMessageConverters().add(index, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            }
    
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders);
    
            UriComponents uriComponents = UriComponentsBuilder.newInstance()
                    .scheme("http")
                    .host("jsonplaceholder.typicode.com")
                    .path("todos")
                    .build();
    
            String urlString = uriComponents.toUriString();
    
            //String.class로 T Body -> String Body
            ResponseEntity<String> responseEntity = restTemplate.exchange(urlString, HttpMethod.GET, httpEntity, String.class);
            HttpHeaders responseHeaders = responseEntity.getHeaders();
            String responseBody = responseEntity.getBody();
    
            System.out.println("http response header debugging start");
            System.out.println(responseHeaders.toString());
            System.out.println();
    
            System.out.println("http response body(String) start");
            System.out.println(responseBody);
            System.out.println();
    
            //JSON처리 작업
            System.out.println("받은 JSON String을 Java객체로 변환");
            GsonBuilder gsonBuilder = new GsonBuilder();
            Gson gson = gsonBuilder.create();
    
            //List.class로 넘기면 Gson은 gson패키지의 LinkedTreeMap인스턴스를 List에 담는다.
            //List<LinkedTreeMap> itemList1 = gson.fromJson(responseBody, List.class);
            //itemList1.forEach(obj -> System.out.println("LinkedTreeMap 인스턴스?: " + Boolean.toString(obj instanceof LinkedTreeMap)));
    
            //방법1
            System.out.println("방법1 start");
            List<Item> itemList2 = gson.fromJson(responseBody, new TypeToken<List<Item>>() {
            }.getType());
            itemList2.forEach(item -> System.out.println(item));
            System.out.println();
    
            //방법2
            System.out.println("방법2 start");
            Item[] itemArray = gson.fromJson(responseBody, Item[].class);
            for (int i = 0; i < itemArray.length; i++) {
                System.out.println(itemArray[i]);
            }
        }
    }

    • Authorization
    HttpHeaders httpHeaders = new HttpHeaders();
    String bearerToken = "토큰 입력";
    httpHeaders.setBearerAuth(bearerToken);

     

     

     

     

     

    댓글

Designed by Tistory.