스프링에서 제공하는 HTTP 통신 기능을 쉽게 사용할 수 있게 설계되어 있는 템플릿
HTTP 서버와의 통신을 단순화하고 RESTful 원칙을 지킴
동기 방식으로 처리되며, 비동기 방식으로는 AsyncRestTemplate이 있음
RestTemplate 클래스는 REST 서비스를 호출하도록 설계되어 HTTP 프로토콜의 메소드에 맞게 여러 메소드를 제공
MemberDTO.java
package com.example.testproject.data.dto;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class MemberDTO {
private String name;
private String email;
private String organization;
}
RestTemplateService.java
package com.example.testproject.data.service;
import com.example.testproject.data.dto.MemberDTO;
import org.springframework.http.ResponseEntity;
import java.lang.reflect.Member;
public interface RestTemplateService {
public String getAroundHub();
public String getName();
public String getName2();
public ResponseEntity<MemberDTO> postDto();
public ResponseEntity<MemberDTO> addHeader();
}
RestTemplateServiceImpl.java
package com.example.testproject.data.service.Impl;
import com.example.testproject.data.dto.MemberDTO;
import com.example.testproject.data.service.RestTemplateService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 RestTemplateServiceImpl implements RestTemplateService {
private final Logger LOGGER = LoggerFactory.getLogger(RestTemplateServiceImpl.class);
@Override
public String getAroundHub() {
//uri는 어떤경로로 요청을 할건지해서 사용하는 클래스
URI uri= UriComponentsBuilder
.fromUriString("httpL//localhost:8081")
.path("/api/server/around-hub")
.encode() //기본적 utf-8로
.build() //return 값 uricomponent 이기때문에
.toUri(); //uri로 바꿔줌
RestTemplate restTemplate=new RestTemplate();
// 응답을 ResponseEntity 객체로 받는다. getForObject()와 달리 HTTP 응답에대한
// 추가 정보를 담고 있어서 GET 요청에 대한 응답 코드, 실제 데이터를 확인할 수 있다.
// 또한 ResponseEntity<T> 제네릭 타입에 따라서 응답을 String이나 Object 객체로 받을 수 있다.
ResponseEntity<String> responseEntity=restTemplate.getForEntity(uri, String.class); //만들어진 uri값과 그 타입과 맞춘 클래스
LOGGER.info("status code: {}", responseEntity.getStatusCode());
LOGGER.info("body : {}", responseEntity.getBody());
return responseEntity.getBody();
}
@Override
public String getName() {
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:8081")
.path("/api/server/name") //위의 getAroundHub와 경로 다름
.queryParam("name", "Flature") //requestparam 넣음
.encode()
.build()
.toUri();
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
LOGGER.info("status code : {}", responseEntity.getStatusCode());
LOGGER.info("body : {}", responseEntity.getBody());
return responseEntity.getBody();
}
@Override
public String getName2() {
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:8081")
.path("/api/server/path-variable/{name}") // expand를 넣어줘서 값을 넣음.
.encode()
.build()
.expand("Flature") // 복수의 값을 넣어야할 경우 , 를 추가하여 구분
.toUri();
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
LOGGER.info("status code : {}", responseEntity.getStatusCode());
LOGGER.info("body : {}", responseEntity.getBody());
return responseEntity.getBody();
}
@Override
public ResponseEntity<MemberDTO> postDto() {
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:8081")
.path("/api/server/member")
.queryParam("name", "Flature")
.queryParam("email", "jjj@jjj.com")
.queryParam("organization", "Around Hub Studio")
.encode()
.build()
.toUri();
//request값에 값을 넣기 위해 사용됨.
MemberDTO memberDTO = new MemberDTO();
memberDTO.setName("flature!!");
memberDTO.setEmail("aaa@aaa.com");
memberDTO.setOrganization("Around Hub Studio!!");
RestTemplate restTemplate = new RestTemplate();
//memberDTO가 들어가게 되고 requestBody로 인식
ResponseEntity<MemberDTO> responseEntity = restTemplate.postForEntity(uri, memberDTO,
MemberDTO.class);
LOGGER.info("status code : {}", responseEntity.getStatusCode());
LOGGER.info("body : {}", responseEntity.getBody());
return responseEntity;
}
@Override
public ResponseEntity<MemberDTO> addHeader() {
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:9090")
.path("/api/server/add-header")
.encode()
.build()
.toUri();
MemberDTO memberDTO = new MemberDTO();
memberDTO.setName("flature");
memberDTO.setEmail("jjj@jjj.com");
memberDTO.setOrganization("Around Hub Studio");
//requestEntity.get .delete .put. patch 다 있음.
RequestEntity<MemberDTO> requestEntity = RequestEntity
.post(uri)
.header("around-header", "Around Hub Studio")
.body(memberDTO);
RestTemplate restTemplate = new RestTemplate();
//header와 body값이 다 들어가있기 때문에 requestEntity만 넣어줌
ResponseEntity<MemberDTO> responseEntity = restTemplate.exchange(requestEntity,
MemberDTO.class);
LOGGER.info("status code : {}", responseEntity.getStatusCode());
LOGGER.info("body : {}", responseEntity.getBody());
return responseEntity;
}
}
package com.example.testproject.controller;
import com.example.testproject.data.dto.MemberDTO;
import com.example.testproject.data.service.RestTemplateService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/server")
public class RestTemplateController {
private final Logger LOGGER= LoggerFactory.getLogger(RestController.class);
private final RestTemplateService restTemplateService;
public RestTemplateController(RestTemplateService restTemplateService){
this.restTemplateService=restTemplateService;
}
@GetMapping(value = "/around-hub")
public String getAroundHub() {
return restTemplateService.getAroundHub();
}
@GetMapping(value = "/name")
public String getName() {
return restTemplateService.getName();
}
@GetMapping(value = "/name2")
public String getName2() {
return restTemplateService.getName2();
}
@PostMapping(value = "/dto")
public ResponseEntity<MemberDTO> postDto() {
return restTemplateService.postDto();
}
@PostMapping(value = "/add-header")
public ResponseEntity<MemberDTO> addHeader() {
return restTemplateService.addHeader();
}
TestController.java
package controller;
import dto.MemberDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/server")
public class TestController {
private final Logger LOGGER= LoggerFactory.getLogger(TestController.class);
@GetMapping(value="/around-hub")
public String getTest1(){
LOGGER.info("getTest1 호출!");
return "Hello, Around Hub Studio!";
}
@GetMapping(value="/name")
public String getTest2(@RequestParam String name){
LOGGER.info("getTest2 호출");
return "Hello. "+name+"!";
}
@GetMapping(value="/path-variable/{name}")
public String getTest3(@PathVariable String name){
LOGGER.info("getTest3 호출");
return "Hello. "+name+"!";
}
@PostMapping(value="/member")
public ResponseEntity<MemberDTO> getMember(
@RequestBody MemberDTO memberDTO,
@RequestParam String name,
@RequestParam String email,
@RequestParam String organization){
LOGGER.info("getMember 호출!");
// MemberDTO memberDTO1=new MemberDTO();
// memberDTO1.setName(name);
// memberDTO1.setEmail(email);
// memberDTO1.setOrganization(organization);
return ResponseEntity.status(HttpStatus.OK).body(memberDTO);
}
@PostMapping(value="/add-header")
public ResponseEntity<MemberDTO> addHeader(@RequestHeader("around-header") String header, @RequestBody MemberDTO memberDTO){
LOGGER.info("add-header 호출!");
LOGGER.info("header 값 : {}", header);
return ResponseEntity.status(HttpStatus.OK).body(memberDTO);
}
}
MemberDTO.java
package dto;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class MemberDTO {
private String name;
private String email;
private String organization;
}
클라이언트(포트8080)의 컨트롤러에서 리턴값으로 @Service의 메소드를 불러냄. 그 메소드들은 localhost:9090에 restapi를 호출하게끔 설계되어있음
서버(포트:9090)는 컨트롤러에서 정의해놓은 로거들을 실행하면서 (EX. getTest1호출!) 정해진 리턴값을 보내줌
그럼 클라이언트의 RestTemplateServiceImpl에서 응답을 ResponseEntity 객체로 받아 바디에 넣어서 리턴해줌
클라이언트
서버
[2022-10-21 02:24:09.943] [INFO ] [http-nio-8080-exec-3] c.e.t.d.s.I.RestTemplateServiceImpl status code : 200 OK
[2022-10-21 02:24:09.943] [INFO ] [http-nio-8080-exec-3] c.e.t.d.s.I.RestTemplateServiceImpl body : Hello. Flature!
2022-10-21 02:24:09.941 INFO 51196 --- [nio-9090-exec-3] c.e.r.controller.TestController : getTest2 호출
RestTemplateServiceImpl.java
부분 postDto 실행될때
public ResponseEntity<MemberDTO> postDto() {
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:9090")
.path("/api/server/member")
.queryParam("name", "Flature")
.queryParam("email", "jjj@jjj.com")
.queryParam("organization", "Around Hub Studio")
.encode()
.build()
.toUri();
//request값에 값을 넣기 위해 사용됨.
MemberDTO memberDTO = new MemberDTO();
memberDTO.setName("flature!");
memberDTO.setEmail("aaa@aaa.com");
memberDTO.setOrganization("Around Hub Studio!!");
RestTemplate restTemplate = new RestTemplate();
//memberDTO가 들어가게 되고 requestBody로 인식
ResponseEntity<MemberDTO> responseEntity = restTemplate.postForEntity(uri, memberDTO,
MemberDTO.class);
LOGGER.info("status code : {}", responseEntity.getStatusCode());
LOGGER.info("body : {}", responseEntity.getBody());
return responseEntity;
}
: MemberDTO의 값이 반영되서 리턴됨을 알 수 있음
@PostMapping(value="/member")
public ResponseEntity<MemberDTO> getMember(
@RequestBody MemberDTO memberDTO,
@RequestParam String name,
@RequestParam String email,
@RequestParam String organization){
LOGGER.info("getMember 호출!");
// MemberDTO memberDTO1=new MemberDTO();
// memberDTO1.setName(name);
// memberDTO1.setEmail(email);
// memberDTO1.setOrganization(organization);
return ResponseEntity.status(HttpStatus.OK).body(memberDTO);
return 값을 보면 body에
memberDTO
가 들어가있음을 알 수 있다. 그러면 주석을 해제하고memberDTO1
값을 body에 담으면 어떻게 될까?
@PostMapping(value="/member")
public ResponseEntity<MemberDTO> getMember(
@RequestBody MemberDTO memberDTO,
@RequestParam String name,
@RequestParam String email,
@RequestParam String organization){
LOGGER.info("getMember 호출!");
MemberDTO memberDTO1=new MemberDTO();
memberDTO1.setName(name);
memberDTO1.setEmail(email);
memberDTO1.setOrganization(organization);
return ResponseEntity.status(HttpStatus.OK).body(memberDTO1);
}
클라이언트의 RestTemplateServiceImpl.java의 메소드 postDto에서
memberDTO
객체를 생성해서 보낸 값들은ResponseEntity<MemberDTO> responseEntity = restTemplate.postForEntity(uri, memberDTO, MemberDTO.class);
에서 request(
memberDTO
)에 담기게 된다
이부분은 서버(TestController.java)에서 @RequestBody 로 불러오는것이 가능해진다.
[2022-10-21 02:29:04.927] [INFO ] [http-nio-8080-exec-5] c.e.t.d.s.I.RestTemplateServiceImpl body : MemberDTO(name=flature!!, email=aaa@aaa.com, organization=Around Hub Studio!!)
[2022-10-21 02:34:55.101] [INFO ] [http-nio-8080-exec-4] c.e.t.d.s.I.RestTemplateServiceImpl status code : 200 OK
2022-10-21 02:34:55.064 INFO 26268 --- [nio-9090-exec-1] c.e.r.controller.TestController : getMember 호출!
클라이언트의 RestTemplateServiceImpl.java의 메소드 postDto에서
쿼리파라미터(.queryParam)
으로 담아준 값(uri에 담김
)들은ResponseEntity<MemberDTO> responseEntity = restTemplate.postForEntity(uri, memberDTO, MemberDTO.class);
서버에서
@RequestParam
으로 받아와져서 객체를 생성(memberDTO1
), 넣어준 뒤에 바디값으로 보내기 때문에MemberDTO memberDTO1=new MemberDTO(); memberDTO1.setName(name); memberDTO1.setEmail(email); memberDTO1.setOrganization(organization); return ResponseEntity.status(HttpStatus.OK).body(memberDTO1);
응답값으로 받아와진다.
[2022-10-21 02:34:55.101] [INFO ] [http-nio-8080-exec-4] c.e.t.d.s.I.RestTemplateServiceImpl body : MemberDTO(name=Flature, email=jjj@jjj.com, organization=Around Hub Studio)
[2022-10-21 02:53:47.056] [INFO ] [http-nio-8080-exec-8] c.e.t.d.s.I.RestTemplateServiceImpl status code : 200 OK
2022-10-21 02:34:55.064 INFO 26268 --- [nio-9090-exec-1] c.e.r.controller.TestController : getMember 호출!
key : header - value : around hub studio 값을 넣어서 보냄
RestTemplateServiceImpl.java
@Override
public ResponseEntity<MemberDTO> addHeader() {
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:9090")
.path("/api/server/add-header")
.encode()
.build()
.toUri();
MemberDTO memberDTO = new MemberDTO();
memberDTO.setName("flature");
memberDTO.setEmail("jjj@jjj.com");
memberDTO.setOrganization("Around Hub Studio");
//requestEntity.get .delete .put. patch 다 있음.
RequestEntity<MemberDTO> requestEntity = RequestEntity
.post(uri)
.header("around-header", "Around Hub Studio")
.body(memberDTO);
RestTemplate restTemplate = new RestTemplate();
//header와 body값이 다 들어가있기 때문에 requestEntity만 넣어줌
ResponseEntity<MemberDTO> responseEntity = restTemplate.exchange(requestEntity,
MemberDTO.class);
LOGGER.info("status code : {}", responseEntity.getStatusCode());
LOGGER.info("body : {}", responseEntity.getBody());
return responseEntity;
}
@RequestHeader
로 받아서 전달됨. @PostMapping(value="/add-header")
public ResponseEntity<MemberDTO> addHeader(@RequestHeader("around-header") String header, @RequestBody MemberDTO memberDTO){
LOGGER.info("add-header 호출!");
LOGGER.info("header 값 : {}", header);
return ResponseEntity.status(HttpStatus.OK).body(memberDTO);
}
[2022-10-21 02:53:47.056] [INFO ] [http-nio-8080-exec-8] c.e.t.d.s.I.RestTemplateServiceImpl status code : 200 OK
[2022-10-21 02:53:47.057] [INFO ] [http-nio-8080-exec-8] c.e.t.d.s.I.RestTemplateServiceImpl body : MemberDTO(name=flature, email=jjj@jjj.com, organization=Around Hub Studio)
2022-10-21 02:53:47.051 INFO 26268 --- [nio-9090-exec-3] c.e.r.controller.TestController : add-header 호출!
2022-10-21 02:53:47.052 INFO 26268 --- [nio-9090-exec-3] c.e.r.controller.TestController : header 값 : Around Hub Studio
인증(authentication)은 헤더값을 통해 많이 사용됨.