프로그래밍/- Java,Spring 초격차 교육
Rest Templete( Rest API )
즐겁게 하하하
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