오답노트

[Spring] Server to Server 본문

Java/Spring

[Spring] Server to Server

권멋져 2023. 7. 14. 16:35

Server to Server

지금까지는 서버를 개발하여 클라이언트의 요청을 처리하기만 했다. 하지만 우리도 누군가의 클라이언트가 되어 요청을 보내고 응답을 받아와야 할 경우가 있다.

 

GET

import com.example.client.dto.UserResponse;
import lombok.extern.slf4j.Slf4j;
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;

@Slf4j
@Service
public class RestTemplateService {

    public UserResponse hello(){

        URI uri = UriComponentsBuilder.fromUriString("http://localhost:8080").path("/api/server/hello")
                .queryParam("name","steve")
                .queryParam("age",20)
                .encode().build().toUri();

        log.info(uri.toString());

        RestTemplate restTemplate = new RestTemplate();
        UserResponse result = restTemplate.getForObject(uri,UserResponse.class);

        return result;


    }

}

UriComponentsBuilder는 Uri를 메소드를 활용하여 만들어주는 클래스다. 적절히 메소드를 활용해 서버의 uri를 만들자.

 

해당 Uri를 RestTemplate의 getForObject 메소드를 통해 서버에 GET을 보낼 수 있다.

 

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

    private final RestTemplateService restTemplateService;

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

    @GetMapping("")
    public UserResponse getHello(){
        return restTemplateService.hello();
    }
}

반환한 내용을 위 코드처럼 활용하여 Client가 우리 Server에 요청을 했을 때, 우리도 Client가 되어 다른 서버에 요청을 보낼 수 있다.

 

POST

    public UserRequest post(){
        URI uri = UriComponentsBuilder.fromUriString("http://localhost:8080").path("/api/server/user/{userid}/name/{username}")
                .encode().build().expand(100,"steve").toUri();

        log.info(uri.toString());

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

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<UserRequest> response = restTemplate.postForEntity(uri,req,UserRequest.class);


        log.info(response.getStatusCode().toString());
        log.info(response.getHeaders().toString());
        log.info(response.getBody().toString());




        return response.getBody();

    }

RestTemplate에서 getForEntity에서 postEntity만 달라졌다.

 

Exchange 와 Generic

RestTemplate의 exchange 메소드는 요청을 보낼 자료형과 응답 받을 자료형이 다를 때 사용한다. (POST 사용)

그리고 보통 응답받을때 어떤 형식의 데이터가 오는지 알 수 없을 수 있다. 이때 제네릭을 활용하면 좋다.

 

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Req<T> {

    private Header header;
    private T rBody;

    @Getter
    @Setter
    public static class Header {
        private String responseCode;
    }

    @Override
    public String toString() {
        return "Req{" +
                "header=" + header +
                ", body=" + rBody +
                '}';
    }
}

어떤 자료형을 받을지 몰라 제네릭 타입인 T를 사용했다.

 

   public Req<UserResponse> generic (){
        URI uri = UriComponentsBuilder.fromUriString("http://localhost:8080").path("/api/server/user/{userid}/name/{username}")
                .encode().build().expand(100,"steve").toUri();

        log.info(uri.toString());

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

        Req req = new Req();
        req.setHeader(
                new Req.Header()
        );

        req.setRBody(
                userRequest
        );


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

        RestTemplate restTemplate = new RestTemplate();

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

        return response.getBody();
    }

T에 UserRequest 형식으로 넘어오는 것을 알고 Generic을 사용한 코드이다.

Generic 타입의 경우 Class 클래스가 적용되지 않는다. 따라서

ParameterizedTypeReference를 통해 자료형을 지정해야한다.

'Java > Spring' 카테고리의 다른 글

[Spring] 코드 Test하기  (0) 2023.07.17
[Spring] Server to Server 예제 (네이버 API)  (0) 2023.07.14
[Spring] 비동기 처리 (Async)  (0) 2023.07.14
[Spring] Interceptor  (0) 2023.07.14
[Spring] Filter  (0) 2023.07.14