BackEnd/패캠

Rest Template (Server to Server 통신)

제이드Jade 2022. 1. 25. 00:00
  • 서버가 클라이언트가 되어서 다른 서버에게 응답을 요청해보자!!!(고로 서버 두개(클:8080, 서:9090)를 쓸 것임)
  • 즉, 브라우저(찐 클라이언트)에서 요청은 그냥 get 으로만 이루어져있음(파라미터, body xx), 그러면 찐 요청은 클라이언트 서버에서 하고, 응답을 서버에서 받아와 찐 클라이언트에게 보냄

 

1)get요청, 2)post요청, 3)헤더가 있는 post요청, 4)제너릭객체를 돌려주는 post요청을 해보자

 

<client>

application.yml -> server.port =8080

 

- controller

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

    private final RestTemplateService restTempleteService;  //이제는 생성자 주입으로 많이 함(autowired xxx)

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

    @GetMapping("/hello")
    public UserResponse hello(){
        return restTempleteService.hello();
    }

    @GetMapping("/user")
    public UserResponse getHello(){
        return restTempleteService.post();

    }

    @GetMapping("/header")
    public UserResponse getHHello(){
        return restTempleteService.exchange();
    }


    @GetMapping("/generic")
    public Req<UserRequest> getGHello(){
        return restTempleteService.genericExchange();
    }
}

 

- service

@Service
public class RestTemplateService {

    //get요청
    public UserResponse hello(){

        URI uri= UriComponentsBuilder         //요청할 주소 만들기 : http://localhost:9090/api/server/hello
                .fromUriString("http://localhost:9090")
                .path("/api/server/hello")
                .queryParam("name","jade")
                .queryParam("age",99)
                .encode() //후에 파라미터를 넣을 때 인코딩 하는게 좋으므로 함
                .build()
                .toUri();

        System.out.println(uri.toString());

        RestTemplate restTemplate=new RestTemplate();  //서버를 클라이언트로 만들어줌,즉 REST 서비스를 호출할 수 있게 함. restTemplate안에 여러 요청 메소드를 쓸 수 있음
        ResponseEntity<UserResponse> result=restTemplate.getForEntity(uri, UserResponse.class);  //해당 uri로 가서 반환되는 string객체를 get요청

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

        return result.getBody();
    }

    //post요청
    public UserResponse post() {
        URI uri=UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/server/user/{userName}/age/{userAge}")  //사실 post에는 paramid필요 x하지만 동작방식을 보여주기 위함
                .encode()
                .build()
                .expand("jade",26)    //주소 path에 pathvariable자리, 즉 {}안에 차례대로 넣어준다.
                .toUri();

        UserRequest req=new UserRequest();
        req.setName("jade");
        req.setAge(26);

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

        System.out.println(result.getStatusCode());
        System.out.println(result.getHeaders());
        System.out.println(result.getBody());

        return result.getBody();

        /*
        * 여기서, response가 무슨 타입으로 올지 모르겠어서 일단 텍스트로 형태를 보고 싶다면,
        * ResponseEntity<String>~ = (~,String.class)으로 받아서 sout해보는 식으로 할 수 있다. (근데 현업에서 모르게 될 일은 거의 x)
        * */
    }

    //헤더 추가해서 요청하기
    public UserResponse exchange() {
        URI uri=UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/server/header/{userName}/age/{userAge}")  //사실 post에는 paramid필요 x하지만 동작방식을 보여주기 위함
                .encode()
                .build()
                .expand("jade",26)    //주소 path에 pathvariable자리, 즉 {}안에 차례대로 넣어준다.
                .toUri();

        UserRequest req=new UserRequest();
        req.setName("jade");
        req.setAge(26);

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

        RestTemplate restTemplate=new RestTemplate();
        ResponseEntity<UserResponse> result=restTemplate.exchange(requestEntity,UserResponse.class);

        return result.getBody();
    }

    //요청을 제너릭으로 받아보자.
//    {
//        Header:"",
//        reqBody:{
    //          name:"",
    //          age:""
//      }
//    }
    public Req<UserRequest> genericExchange() {
        URI uri=UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/server/generic/{userName}/age/{userAge}")  //사실 post에는 paramid필요 x하지만 동작방식을 보여주기 위함
                .encode()
                .build()
                .expand("jade",26)    //주소 path에 pathvariable자리, 즉 {}안에 차례대로 넣어준다.
                .toUri();

        UserRequest userRequest=new UserRequest();
        userRequest.setName("jade");
        userRequest.setAge(26);

        Req<UserRequest> req=new Req<>();   //제너릭객체 만들기
        req.setHeader(new Req.Header());
        req.setReqBody(userRequest);        //바디는 아까 만든 바디

        RequestEntity<Req<UserRequest>> requestEntity= RequestEntity
                                                    .post(uri)
                                                    .contentType(MediaType.APPLICATION_JSON)
                                                    .header("x-authorization","nanana")
                                                    .header("custom-header","alala")
                                                    .body(req);     //제너릭객체를 바디로

        RestTemplate restTemplate=new RestTemplate();
        ResponseEntity<Req<UserRequest>> result
                = restTemplate.exchange(requestEntity, new ParameterizedTypeReference<Req<UserRequest>>(){});
    //제너릭객체는 .class로 명시x Parameterized~로 받아야 한다.
        return result.getBody();
    }
}

 

dto

- Response

public class UserResponse {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + 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;
    }
}

 

- Request

public class UserRequest {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + 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;
    }
}

 

- Req<T>

public class Req<T> {

    private Header header;
    private T reqBody;

    public static class Header{
        private String responseCode;

        public String getResponseCode() {
            return responseCode;
        }

        public void setResponseCode(String responseCode) {
            this.responseCode = responseCode;
        }

        @Override
        public String toString() {
            return "Header{" +
                    "responseCode='" + responseCode + '\'' +
                    '}';
        }
    }

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

    public Header getHeader() {
        return header;
    }

    public void setHeader(Header header) {
        this.header = header;
    }

    public T getReqBody() {
        return reqBody;
    }

    public void setReqBody(T reqBody) {
        this.reqBody = reqBody;
    }
}

 

<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("/user/{userName}/age/{userAge}")  //클라이언트 서버로부터 온 UserRequest가 json형태로 받아지고 이게 다시 User로 매핑
    public User user(@RequestBody User user, @PathVariable String userName, @PathVariable int userAge){
        log.info("userName:{}, userAge:{} ",userName,userAge);
        log.info("clientReq: {}",user);

        return user;
    }

    @PostMapping("/header/{userName}/age/{userAge}")  //헤더 추가된 요청받기
    public User post(@RequestBody User user,
                     @PathVariable String userName,
                     @PathVariable int userAge,
                     @RequestHeader("x-authorization") String authorization,
                     @RequestHeader("custom-header") String customHeader){

        log.info("userName:{}, userAge:{} ",userName,userAge);
        log.info("clientReq: {}",user);
        log.info("x-authorization: {}",authorization);
        log.info("custom-header : {}",customHeader);

        return user;
    }

    //헤더+요청객체 내에 제너릭타입의 객체가 또 있을 때
    @PostMapping("/generic/{userName}/age/{userAge}")
    public Req<User> gpost(@RequestBody Req<User> user,
                           @PathVariable String userName,
                           @PathVariable int userAge,
                           @RequestHeader("x-authorization") String authorization,
                           @RequestHeader("custom-header") String customHeader
                           //HTTPEntity<String> entity  => user대신에 이걸 쓰면 요청 객체를 string 형으로 받는다. 디버깅에 유용.
    ){

        log.info("userName:{}, userAge:{} ",userName,userAge);
        log.info("x-authorization: {}",authorization);
        log.info("custom-header : {}",customHeader);
        log.info("clientReq: {}",user);
//        log.info("req:{}",entity)

        Req<User> response=new Req<>();
        response.setHeader(new Req.Header());
        response.setReqBody(user.getReqBody());

        return response;
    }
}

 

-dto

-User (=response)

 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;
    private int age;
}

 

 -req<T>

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Req<T> {
    private Header header;
    private T reqBody;

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