즐겁게 하하하 2022. 2. 13. 19:39
728x90
Spring 5.0 버전부터는 RestTemplate 은 유지 모드로 변경되고 향후 deprecated 될 예정입니다.
RestTemplate 의 대안으로 Spring 에서는 WebClient 사용을 강력히 권고
 
 

Rest Templete 이용해서 GET 통신

UriComponentsBuilder 이용해서 주소를 만드는 방법

1. Client (브라우저->서버(클라이언트)

API Controller
_______________________
@RestController
@RequestMapping("/api/client")
public class ApiController {

    public final RestTempleteService restTemplateService;

    public ApiController(RestTempleteService restTemplateService) {
        this.restTemplateService = restTemplateService;
    }

    @GetMapping("/hello")
    public UserResponse getHello(){
        return restTemplateService.hello();  :: Get 방식의 요청
    }

    @GetMapping("/hello2")
    public UserResponse postHello(){
        return restTemplateService.post();  :: Post 요청
    }

    @GetMapping("/hello3")
    public UserResponse postHello3(){
        return restTemplateService.exchange();  :: Post 요청, 요청 데이터를 직접 정의
    }

    @GetMapping("/hello4")
    public Req<UserResponse> postHello4(){
        return restTemplateService.genericExchchange();  :: Post 요청, generic 타입을 이용
    }
}
 
Service
_________________________
@Slf4j
@Service
public class RestTempleteService {
    ______________________________________________________________
    :: Get 방식의 요청 Service 
    :: http://localhost/api/service/hello

    public UserResponse hello(){ 
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/server/hello")
                .queryParam("name", "steve")
                .queryParam("age", 99)
                .encode()
                .build()
                .toUri(); 
        System.out.println(uri.toString()); 

        RestTemplate restTemplate = new RestTemplate(); 
        //String result = restTemplate.getForObject(uri, String.class);
        //return result;
        
        :: getForObject , getForEntity 실행되는 순간이
        :: 클라이언트 에서 http로 서버에 GET 으로 붙는 순간
        ResponseEntity<UserResponse> result 
            = restTemplate.getForEntity(uri , UserResponse.class);

        System.out.println(result.getStatusCode());
        System.out.println(result.getBody());
        return result.getBody();
    } 

   ______________________________________________________________
   응답 body : json데이터
	{
		"name": "ugo",
		"age": 100
	}

    :: Post 요청 Service
    :: http://localhost:9090/api/server/user/{userId}/name/{username}

    public UserResponse post(){ 
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/server/user1/{userAge}/name1/{userName}")
                .encode()
                .build()
                .expand(100,"ugo")
                .toUri();
        log.info("{} " ,uri);

        :: object를 넣어주면 object mapper가 json으로 바꿔주고
        :: rest template에서 http body에 json을 넣어줄 것이다.

        UserRequest req = new UserRequest();
        req.setName("steve");
        req.setAge(10);

        RestTemplate restTemplate = new RestTemplate();

        :: uri에 req object를 보내서 응답은 UserResponse.class타입으로 받을 것이다!!
        ResponseEntity<UserResponse> response = 
           restTemplate.postForEntity(uri, req, UserResponse.class);

        log.info("{} " ,"@ HTTP CODE확인: "+  response.getStatusCode());
        log.info("{} " ,"@ HTTP Header확인: "+ response.getHeaders());
        log.info("{} " ,"@ BODY 확인: "+ response.getBody());
        return response.getBody();
    }

    ______________________________________________________________
    응답 body : 
	{
		"name": "ugo",
		"age": 100
	}

    :: post 방식에서 요청 데이터를 직접 정의하는 방법
    :: ResquestEntity를 만들어 직접 정의하고
    :: restTemplate의 exchange를 통해 넘기는 방식

    public UserResponse exchange(){ 
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/server/user2/{userAge}/name2/{userName}")
                .encode()
                .build()
                .expand(100,"ugo")
                .toUri();
        log.info("{} " ,uri);
  
        UserRequest req = new UserRequest();
        req.setName("steve");
        req.setAge(10);
       
        :: (Post header)
        RequestEntity<UserRequest> requestRequestEntity = RequestEntity
                .post(uri) //요청 방식
                .contentType(MediaType.APPLICATION_JSON) //타입
                .header("x-authorization", "abcde") //헤더 key 값과 value
                .header("custom-header" , "fffff")
                .body(req); // 요청 바디(요청 데이터)

        RestTemplate restTemplate = new RestTemplate();

        :: 헤더를 함께 보낼때는 exchange메서드를 사용한다
        :: 1 요청정보들이 들어있는 entity, 2 응답받을 타입
        ResponseEntity<UserResponse> response = restTemplate
                .exchange(requestRequestEntity , UserResponse.class);

        return response.getBody();
    }
 
   ______________________________________________________________
   응답 body : 
	{
		"header":{
			"responseCode": null
		},
		"resBody":{
			"name": "steve",
			"age": 10
		}
	}
     
    :: 특정 키값(header,body)은 고정되고 그 안에 들어가는 값들만 변경되는 경우
    :: 요청과 응답 데이터의 틀을 만들어 놓고 데이터는 달라질 수 있게 API를 디자인 한다.
    :: generic을 사용하며 , header 값은 고정, body 값은 변경될 수 있는 상황을 예로
    :: {"header": { } , "body" :{ } } 형식을 디자인 한다.

    public Req<UserResponse> genericExchchange(){

        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/server/user3/{userAge}/name3/{userName}")
                .encode()
                .build()
                .expand(100,"ugo")
                .toUri();
        log.info("{} " ,uri);

        :: object를 넣어주면 object mapper가 json으로 바꿔주고
        :: rest template에서 http body에 json을 넣어줄 것이다.

        UserRequest userRequest = new UserRequest();
        userRequest.setName("steve");
        userRequest.setAge(10);

        Req<UserRequest> req = new Req<>();
        req.setHeader(  new Req.Header()  );
        req.setResBody(  userRequest );

        :: (Post header)
        RequestEntity<Req<UserRequest>> requestEntity = RequestEntity
                .post(uri)
                .contentType(MediaType.APPLICATION_JSON)
                .header("x-authorization", "abcde")
                .header("custom-header" , "fffff")
                .body(req);

        RestTemplate restTemplate = new RestTemplate();

        :: 제네릭엔 클래스를 바로 사용할 수 없다.
        :: 아래처럼 ParameterizedTypeReference로 한번 감싸 타입을 갖게 한다.

        ResponseEntity<Req<UserResponse>> response
                = restTemplate.exchange(
                     requestEntity, 
                     new ParameterizedTypeReference<Req<UserResponse>>(){}
                  );

        // getBody() 는 reponseEntity의 응답 body 이고,
        // getrBody는 그 응답바디 안의 필드명이다.
        return response.getBody();
    }
}
 
Dto
___________________________
public class UserResponse {

    private String name;
    private int age;

    public String getName() {  return name;  }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age;  }
    public void setAge(int age) {  this.age = age; }

    @Override
    public String toString() {
        return "UserResponse{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
___________________________
public class UserRequest {

    private String name;
    private int age;

    public String getName() {  return name;  }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age;  }
    public void setAge(int age) {  this.age = age; }

    @Override
    public String toString() {
        return "UserResponse{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
___________________________
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Req<T> {

    private Header header; 
    private T resBody;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Header{
        private String responseCode;
    }
}
 

2. Server

Controller
_______________________
@Slf4j
@RestController
@RequestMapping("/api/server")
public class ServerApiController {
   ______________________________________________________________
    @GetMapping("/hello")
    public User hello(@RequestParam String name, @RequestParam int age){
        User user = new User();
        user.setName(name);
        user.setAge(age);
        return user;
    }
   ______________________________________________________________ 
    @PostMapping(value =  "/user1/{userAge}/name1/{userName}", 
            produces = "application/json; charset=utf-8")
    public User post1(  @PathVariable int userAge, @PathVariable String userName ){
        User user = new User();
        user.setName(userName);
        user.setAge(userAge);
        log.info("userId:{},userName:{}",userAge ,userName);
        return user;
    }
   ______________________________________________________________ 
    @PostMapping(value =  "/user2/{userAge}/name2/{userName}", 
            produces = "application/json; charset=utf-8")
    public User post2(
            @RequestBody User user,
            @PathVariable int userAge,
            @PathVariable String userName,
            @RequestHeader("x-authorization") String authorization,
            @RequestHeader("custom-header") String customHeader
    ){

        log.info("authorization:{},customHeader:{}",authorization ,customHeader);
        log.info("userId:{},userName:{}",userAge ,userName);
        log.info("client request:{}",user);
        return user;
    }
   ______________________________________________________________
    @PostMapping(value =  "/user3/{userAge}/name3/{userName}", 
            produces = "application/json; charset=utf-8")
    public Req<User> post3(

            :: 클라이언트가 나한테 뭘보냈는지 모르겠다??
            :: @RequestBody Req<User> user 주석 처리 후
            :: HttpEntity<String> entity 사용.
            @RequestBody Req<User> user,
            @PathVariable int userAge,
            @PathVariable String userName,
            @RequestHeader("x-authorization") String authorization,
            @RequestHeader("custom-header") String customHeader
    ){

        log.info("======================");
        :: log.info("req entity:{}",entity.getBody()); //인자값 디버깅
        log.info("authorization:{},customHeader:{}",authorization ,customHeader);
        log.info("userId:{},userName:{}",userAge ,userName);
        log.info("client request:{}",user);

        Req<User> response = new Req<>();
        response.setHeader(  new Req.Header() );
        response.setResBody( user.getResBody() );
        return response;
    }
   ______________________________________________________________
}
 
Dto
___________________________
@Data                // getter , setter , toString.. 등
@NoArgsConstructor   // 기본생성자
@AllArgsConstructor  // 전체 생성자
public class User {
    private String name;
    private int age;
}
___________________________
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Req<T> {

    private Header header;
    private T resBody;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Header{
        private String responsecode;
    }
}
 

 


 

네이버 검색 api 지역검색 연동

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

    //https://openapi.naver.com/v1/search/local.json?
    // query=%EC%A3%BC%EC%8B%9D  &display=10 &start=1 &sort=random
    @GetMapping("/naver")
    public String naver(){

       //get query parameter
        URI uri = UriComponentsBuilder
                .fromUriString("https://openapi.naver.com")
                .path("/v1/search/local.json")
                .queryParam("query", "갈비찜" )
                .queryParam("display" , 10)
                .queryParam( "start" , 1)
                .queryParam( "sort" , "random" )
                .encode( Charset.forName("UTF-8") )
                .build()
                .toUri();

        //get header
        RequestEntity<Void> req = RequestEntity
                .get(uri)
                .header("X-Naver-Client-Id" , "piqWzRgTEONmDcvBrr5f")
                .header("X-Naver-Client-Secret" , "QOduarHcZF")
                .build();

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> result = restTemplate.exchange( req , String.class );

        return result.getBody();
    }
}
 
 

 

 

728x90