우선 Client(보내는 입장)와 받는 입장인 Server 를 이용할 것이기 때문에
IntelliJ를 두 개를 킨 후 각각의 프로젝트를 만든다.
Client port는 8080, Server port는 9090으로 진행한다.
get API를 사용할 때 어떤 서버가 어떠한 데이터를 제공함.
JSON의 표준 규격을 보고 클래스를 생성한다.
클래스를 작성 후 RestTemplate의 통해서 get, post 등으로 데이터를 주고받음.
get같은 경우 이 예시는 주소를 호출하기만 하면 되기때문에 문제가 되지 않음.
post로 보낼 경우 RequestBody를 붙여서 보내야 하기 때문에 이후에 알아보기로 하자.
Client -> Server로 요청해서 응답을 받는 형태
Client
- ApiController.java
package com.example.client.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
// Req<T> -> 제네릭 타입 T
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Req<T> {
// header 가 들어감
private Header header;
private T responseBody;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Header{
private String responseCode;
}
}
- Req.java
package com.example.client.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
// Req<T> -> 제네릭 타입 T
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Req<T> {
// header 가 들어감
private Header header;
private T responseBody;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Header{
private String responseCode;
}
}
- UserRequest.java
package com.example.client.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserRequest {
private String name;
private int age;
}
- UserResponse.java
package com.example.client.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserResponse {
private String name;
private int age;
}
- RestTemplateService.java
package com.example.client.service;
import com.example.client.dto.Req;
import com.example.client.dto.UserRequest;
import com.example.client.dto.UserResponse;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
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;
@Service
public class RestTemplateService {
// http://localhost/api/server/hello
// response
// getBody 안에는 UserResponse가 들어있기 때문에 반환 값은 UserResponse
public UserResponse hello(){
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:9090")
.path("/api/server/hello")
.queryParam("name","aaaa")
.queryParam("age",9999) // 주소 뒤에 쿼리파라미터가 붙음.
.encode()
.build()
.toUri();
System.out.println(uri.toString());
RestTemplate restTemplate = new RestTemplate();
//String result = restTemplate.getForObject(uri, String.class);
ResponseEntity<UserResponse> result = restTemplate.getForEntity(uri, UserResponse.class);
//헤더 내용이나 상세한 정보를 알기 위해서는 ResponseEntity로 받는 것이 용이
// getForObject, getForEntity 에서의 get은 get,post메서드의 get임.
System.out.println(result.getStatusCode()); //200 OK 출력
System.out.println(result.getBody()); // hello server 출력
return result.getBody();
}
public UserResponse post(){
//http://localhost:9090/api/server/user/{userId}/name/{userName}
//UriComponentBuilder에서 Path Variable 바꾸는 법
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:9090")
.path("/api/server/user/{userId}/name/{userName}")
.encode()
.build()
.expand(100, "steve") // path의 1, 2번째 {}와 매칭. ","로 계속 이어 붙이면 됨.
.toUri();
System.out.println(uri);
// http body -> object -> object mapper -> json -> rest tamplate ->
// http body json
UserRequest req = new UserRequest();
req.setName("steve");
req.setAge(10);
RestTemplate restTemplate = new RestTemplate();
//ResponseEntity를 UserResponse 타입으로 받음.
//해당 주소(uri)에 req를 만들어서 UserResponse로 받음.
ResponseEntity<UserResponse> response = restTemplate.postForEntity(uri, req, UserResponse.class);
System.out.println(response.getStatusCode());
System.out.println(response.getHeaders());
System.out.println(response.getBody());
return response.getBody();
}
public UserResponse exchange(){
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:9090")
.path("/api/server/user/{userId}/name/{userName}")
.encode()
.build()
.expand(100, "steve") // path의 1, 2번째 {}와 매칭. ","로 계속 이어 붙이면 됨.
.toUri();
System.out.println(uri);
// http body -> object -> object mapper -> json -> rest tamplate ->
// http body json
UserRequest req = new UserRequest();
req.setName("steve");
req.setAge(10);
RequestEntity<UserRequest> requestEntity = RequestEntity
.post(uri)
.contentType(MediaType.APPLICATION_JSON)
.header("x-authorization","abcd")
.header("custom-header","fffff")
.body(req);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<UserResponse> response = restTemplate.exchange(requestEntity, UserResponse.class);
return response.getBody();
}
public Req<UserResponse> genericUserExChange(){
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:9090")
.path("/api/server/user/{userId}/name/{userName}")
.encode()
.build()
.expand(100, "steve") // path의 1, 2번째 {}와 매칭. ","로 계속 이어 붙이면 됨.
.toUri();
System.out.println(uri);
// http body -> object -> object mapper -> json -> rest tamplate ->
// http body json
UserRequest userRequest = new UserRequest();
userRequest.setName("steve");
userRequest.setAge(10);
Req<UserRequest> req = new Req<UserRequest>();
req.setHeader(
new Req.Header()
);
req.setResponseBody(
userRequest
);
RequestEntity<Req<UserRequest>> requestEntity = RequestEntity
.post(uri)
.contentType(MediaType.APPLICATION_JSON)
.header("x-authorization","abcd")
.header("custom-header","fffff")
.body(req);
// generic에는 class를 붙일 수 없음. 그래서 아래 코드를 작성하여 class 가 들어갈 곳으로 넣어줌.
//new ParameterizedTypeReference<Req<UserResponse>>(){};
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Req<UserResponse>> response
= restTemplate.exchange(requestEntity, new ParameterizedTypeReference<Req<UserResponse>>(){});
return response.getBody();
}
}
Server
- ServerApiController.java
package com.example.server.controller;
import com.example.server.dto.Req;
import com.example.server.dto.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@RequestMapping("/api/server")
public class ServerApiContoller {
@GetMapping("/hello")
public User hello(@RequestParam String name, @RequestParam int age){
User user = new User();
user.setName(name);
user.setAge(age);
return user;
}
// header 변수 넣어주기
// JSON의 형태가 헤더와 바디로 이루어져 있을 경우가 있음.
// 그럴 경우의 소스코드
@PostMapping("/user/{userId}/name/{userName}")
public Req<User> post(
//오류가 났을 때 뭐가 문제인지 모를 경우에, 아래 소스를 삽입
//함으로써 String의 형태로 로그를 찍어볼 수 있음.
//HttpEntity<String> entity,
@RequestBody Req<User> user,
@PathVariable int userId,
@PathVariable String userName,
@RequestHeader("x-authorization") String authorization,
@RequestHeader("custom-header") String customHeader
){
//log.info("req : {}", entity.getBody());
log.info("userId : {}, userName : {}",userId, userName);
log.info("authorization : {}, custom : {}",authorization, customHeader);
//log.info("client req: {}",user);
Req<User> response = new Req<>();
response.setHeader(
new Req.Header()
);
response.setResponseBody(user.getResponseBody());
return response;
}
}
- Req.java
package com.example.server.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Req<T> {
private Header header;
private T responseBody;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Header{
private String responseCode;
}
}
- User.java
package com.example.server.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String name;
private int age;
}
'개발공부 > Spring Boot' 카테고리의 다른 글
[Spring Boot] JUnit으로 테스트하기 (0) | 2022.03.13 |
---|---|
[Spring Boot] Naver 지역 검색 API 연동해보기 (0) | 2022.03.12 |
[Spring Boot] 비동기 처리하기 (0) | 2022.03.02 |
[Spring Boot] Interceptor (0) | 2022.03.01 |
[Spring Boot] Spring Boot Filter, lombok (0) | 2022.02.22 |