RestTemplate란?
Spring 3.0부터 지원하는 라이브러리로 간편하게 Rest 방식 API를 호출할 수 있습니다.
Restful API 서비스를 요청 후 응답받을 수 있도록 설계되었습니다.
Spring 5부터는 WebFlux 스택과 함께 WebClient라는 새로운 HTTP 클라이언트를 도입하여 기존의 동기식 API를 제공할 뿐만 아니라 효율적인 비차단 및 비동기 접근 방식을 지원하여 RestTemplate는 deprecated 되었습니다.
따라서 WebClient 사용을 지향합니다.
RestTemplate Method
Method | Operation | Action |
delete() | DELETE | 지정된 URL의 리소스에 대해 HTTP DELETE 요청을 수행합니다. |
getForEntity() | GET | HTTP GET 요청을 보내 응답 본문에서 매핑된 개체를 포함하는 ResponseEntity를 반환합니다. |
getForObject() | GET | HTTP GET 요청을 보내 응답 본문에서 매핑된 개체를 반환합니다. |
postForEntity() | POST | 데이터를 URL에 POST하고 응답 본문에서 매핑된 개체를 포함하는 ResponseEntity를 반환합니다. |
postForLocation() | POST | 데이터를 URL에 POST하여 새로 생성된 리소스의 URL을 반환합니다. |
postForObject() | POST | 데이터를 URL에 POST하고 응답 본문에서 매핑된 개체를 반환합니다. |
put() | PUT | 리소스 데이터를 지정된 URL에 PUT합니다. |
patchForObject() | PATCH | HTTP PATCH 요청을 보내 응답 본문에서 매핑된 결과 개체를 반환합니다. |
headForHeaders() | HEAD | HTTP HEAD 요청을 보내 지정된 리소스 URL에 대한 HTTP 헤더를 반환합니다. |
exchange() | ANY | URL에 대해 지정된 HTTP 메서드를 실행하여 개체를 포함하는 ResponseEntity를 반환합니다. |
execute() | ANY | URL에 대해 지정된 HTTP 메서드를 실행하여 응답 본문에서 매핑된 개체를 반환합니다. |
optionsForAllow() | OPTIONS | HTTP OPTIONS 요청을 전홍하여 지정된 URL에 대한 Allow 헤더를 반환합니다. |
메서드를 잘 보시면 postForEntity(), postForObject()와 같이 메서드 이름이 Entity와 Object로 구분되어 있는 것이 있는데 차이점은 Reponse입니다.
forEntity는 아래와 같이 ResponseEntity를 반환합니다.
ResponseEntity<CommonResponse> response =
restTemplate.postForEntity(USER_URL, request, CommonResponse.class);
forObject는 ResponseEntity가 아닌 객체를 직접 반환합니다.
CommonResponse response =
restTemplate.postForObject(USER_URL, request, CommonResponse.class);
메서드의 자세한 내용은 여기에서 확인할 수 있습니다.
RestTemplate 사용 방법
- RestTemplate 객체 생성
- HttpHeader setting
- body setting
- HttpEntity 생성
- API 호출
- Response parsing
1) RestTemplate 객체 생성
RestTemplate restTemplate = new RestTemplate();
2) HttpHeader를 setting
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
3) Body Setting
parameter를 setting합니다.
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("userName", "hong");
body.add("age", 25);
4) HttpEntity 생성
HttpEntity<?> requestMessage = new HttpEntity<>(body, httpHeaders);
5) API 호출
HttpEntity<String> response = restTemplate.postForEntity(url, requestMessage, String.class);
6) Response parsing
Object로 데이터를 받았다면 parsing 단계가 필요 없지만 String으로 받았다면 parsing 단계가 필요합니다.
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
UserDto dto = objectMapper.readValue(response.getBody(), UserDto.class);
RestTemplate example
예제를 실행하기 위해 다음과 같은 코드를 미리 작성합니다.
또한 이 게시글에서는 일반적으로 사용하는 GET, POST, PUT, DELETE만 예제를 기록합니다.
package com.example.demo.domain;
import com.example.demo.UserParam;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Getter
@Setter
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "t_user")
public class User {
@Id
private String userId;
private String userName;
private Integer age;
public User(UserParam param) {
this.userId = param.getUserId();
this.userName = param.getUserName();
this.age = param.getAge();
}
}
package com.example.demo.domain;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, String> {
}
package com.example.demo;
import com.example.demo.domain.User;
import com.example.demo.domain.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@RequestMapping("/user")
@RestController
@RequiredArgsConstructor
public class UserController {
private final UserRepository userRepository;
/**
* ContentType에 APPLICATION_FORM_URLENCODED를 사용하지 않는 경우
* RequestBody Annotation을 사용해야 함.
* @param param
* @return
*/
@PostMapping
public CommonResponse add(@Valid @RequestBody UserParam param) {
User user = new User(param);
userRepository.save(user);
return new CommonResponse();
}
@PostMapping("/form")
public CommonResponse addForm(@Valid UserParam param) {
User user = new User(param);
userRepository.save(user);
return new CommonResponse();
}
@GetMapping("/{id}")
public UserDto get(@PathVariable String id) throws Exception {
User user = userRepository.findById(id).orElseThrow(() -> new Exception("사용자 정보가 없습니다."));
return new UserDto(user);
}
@GetMapping
public List<User> list() {
return userRepository.findAll();
}
@PutMapping("/{id}")
public void modify(@PathVariable String id, @RequestBody UserDto param) throws Exception {
User user = userRepository.findById(id).orElseThrow(() -> new Exception("사용자 정보가 없습니다."));
user.setUserName(param.getUserName());
user.setAge(param.getAge());
userRepository.save(user);
}
@DeleteMapping("/{id}")
public void del(@PathVariable String id) {
userRepository.deleteById(id);
}
}
1) postForEntity
@RequestMapping("/user/add/entity")
public CommonResponse addUserEntity() {
RestTemplate restTemplate = new RestTemplate();
// 헤더 설정
HttpHeaders headers = new HttpHeaders();
// MultiValueMap를 사용할 경우 default값이 APPLICATION_FORM_URLENCODED
//headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// 파라미터 세팅
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("userId", "lim");
map.add("userName", "임꺽정");
map.add("age", "21");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
ResponseEntity<CommonResponse> response =
restTemplate.postForEntity(USER_URL + "/form", request, CommonResponse.class);
return response.getBody();
}
API 테스트를 위해 제일 먼저 해야 할 것은 ADD입니다. ADD에 해당하는 HTTP method는 POST입니다.
POST로 파라미터를 보내기 위한 방법은 두 가지가 있습니다.
- MultiValueMap
- MultiValueMap을 사용할 경우 ContentType의 default 값은 application/x-www-form-urlencoded 입니다.
- Class
- Class를 사용할 경우 ContentType의 default 값은 application/json입니다.
이 글에서는 예제의 다양성을 위해 postForEntity에는 MultiValueMap를 사용하고 postForObject에는 Class를 사용했지만 파라미터를 보내는 방식과 postForEntity/postForObject는 관계없습니다.
2) postForObject
@RequestMapping("/user/add")
public CommonResponse addUserObject() {
RestTemplate restTemplate = new RestTemplate();
// 헤더 설정
HttpHeaders headers = new HttpHeaders();
// 파라미터 세팅
UserDto user = new UserDto();
user.setUserId("hong");
user.setUserName("홍길동");
user.setAge(26);
HttpEntity<UserDto> request = new HttpEntity<>(user, headers);
return restTemplate.postForObject(USER_URL, request, CommonResponse.class);
}
3) getForObject
@RequestMapping("/user/list")
public List<User> list () {
RestTemplate restTemplate = new RestTemplate();
User[] users = restTemplate.getForObject(USER_URL, User[].class);
if(users == null) {
return new ArrayList<>();
}
return Arrays.asList(users);
}
추가를 했으면 목록에서 확인해야겠죠. 목록 조회를 getForObject로 만들어 봤습니다.
목록을 받기 위해서 responseType을 배열로 선언했습니다. User[].class 대신 List.class를 사용하면 ClassCastException이 발생합니다.
4) getForEntity
@RequestMapping("/user/info")
public UserDto info () {
RestTemplate restTemplate = new RestTemplate();
UserDto user = restTemplate.getForObject(USER_URL + "/{id}", UserDto.class, "hong");
if(user == null) {
return new UserDto();
}
return user;
}
데이터를 수정하기 전에 수정 화면을 호출하기 위한 사용자 정보 조회입니다.
Restful API에서는 보통 pk를 URL/PK 와 같이 사용하는데, 위 코드에서 USER_URL/hong으로 직접 URL을 입력해도 되지만, 아래 첨부된 이미지와 같이 3번째 인자부터는 uriVariables이기 때문에 "hong"을 3번째 인자에 넣었습니다.
만약 인자를 2개, 3개 넣어야 하는 경우에는 아래와 같이 하면 됩니다.
restTemplate.getForObject(
USER_URL + "/{id}/{id2}/{id3}",
UserDto.class,
"hong",
"id2",
"id3");
5) put
@RequestMapping("/user/modify")
public boolean modify() {
RestTemplate restTemplate = new RestTemplate();
// 헤더 설정
HttpHeaders headers = new HttpHeaders();
// 수정할 정보를 setting
UserDto user = new UserDto();
user.setUserName("홍길동2");
user.setAge(30);
HttpEntity<UserDto> request = new HttpEntity<>(user, headers);
restTemplate.put(USER_URL + "/{id}", request, "hong");
return true;
}
6) delete
@RequestMapping("/user/del")
public boolean del() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.delete(USER_URL + "/{id}", "hong");
return true;
}
참고
RestTemplate (Spring Framework 5.3.23 API)
Synchronous client to perform HTTP requests, exposing a simple, template method API over underlying HTTP client libraries such as the JDK HttpURLConnection, Apache HttpComponents, and others. The RestTemplate offers templates for common scenarios by HTTP m
docs.spring.io
https://www.geeksforgeeks.org/spring-resttemplate/
Spring - RestTemplate - GeeksforGeeks
A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.
www.geeksforgeeks.org
https://juntcom.tistory.com/141
[spring] 스프링에서 사용하는 RestTemplate - http 라이브러리
RestTemplate이란 스프링에서 제공하는 http 통신에 유용하게 쓸 수 있는 템플릿 Spring 3부터 지원 되었고 REST API 호출이후 응답을 받을 때까지 기다리는 동기방식이다 AsyncRestTemplate Spring 4에 추가된
juntcom.tistory.com
https://blog.naver.com/hj_kim97/222295259904
[Spring]스프링 RestTemplate
스프링 RestTemplate - RestTemplate란? - RestTemplate의 특징 - RestTemplate 동작 원리 - AP...
blog.naver.com
https://luvstudy.tistory.com/52
RestTemplate list 반환하기
요청을 반환받는 클래스가 다음과 같다고 가정한다. @Data public class ResultClass { private long idx; private String name; } List로 리턴 받는 방법 - 문제가 있음. 비추천 List list = restTemplate.getFor..
luvstudy.tistory.com
'back end > java' 카테고리의 다른 글
[java] List를 문자열로 Join하는 방법 (0) | 2022.10.17 |
---|---|
spring pageable를 이용한 페이징 처리 (0) | 2022.10.13 |
spring boot jpa에서 SQLite 사용하는 방법 (0) | 2022.10.08 |
Java Bean Validation 사용방법 - ControllerAdvice (0) | 2022.10.03 |
java에서 천단위 쉼표, 소수점 반올림 하는 방법 (0) | 2022.09.05 |