PUT 방식은 HTTP 메서드 중 하나로, 리소스를 생성하거나 업데이트할 때 사용된다. 주로 RESTful API에서 특정 리소스를 완전히 대체하거나 수정할 때 사용된다.
주요 특징
전체 업데이트
- PUT 요청은 클라이언트가 서버에 특정 리소스의 전체 데이터를 보내 해당 리소스를 완전히 대체하거나 새로 생성하는 요청이다. 즉, 리소스의 일부가 아닌 전체 데이터를 전송하여 갱신한다.
멱등성
- PUT 요청은 멱등성을 가진다. 즉, 동일한 요청을 여러번 보내도 결과가 동일하다. 예를 들어 동일한 데이터를 PUT 요청으로 여러 번 보내도 리소스 상태는 변하지 않는다.
리소스 식별
- PUT 요청은 URL을 통해 업데이트 할 리소스를 명확히 식별한다. 예를 들어 /user1/1 URL로 PUT 요청을 보내면, ID가 1인 사용자를 업데이트 하거나, 해당 리소스가 존재하지 않으면 새로 생성한다.
요청 데이터
{
"name" : "mike",
"age" : 30,
"car_list" : [
{
"name" : "M3",
"car_number" : "22너 3341"
},
{
"name" : "R8",
"car_number" : "33너 1234"
}
]
}
package com.tenco.demo_v1.dto;
import java.util.List;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Data;
@Data
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserDTO {
private String name;
private Integer age;
//@JsonProperty("car_list")
private List<CarDTO> carList;
// 비 정적 내부 클래스
class CarDTO {
private String name;
//@JsonProperty("car_number")
private String carName;
}
}
PutApiController 생성
package com.tenco.demo_v1.controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.tenco.demo_v1.dto.UserDTO;
@RestController // IoC (싱글톤 패턴으로 관리 됨 )
public class PutApiController {
/**
* 주소설계
* http://localhost:8080/put/demo1/100
*
* @return JSON
*/
@PutMapping("/put/demo1/{id}")
public UserDTO putMethodName(@PathVariable(name = "id") String id,
@RequestBody UserDTO userDTO) {
System.out.println("id : " + id);
System.out.println("userDTO " + userDTO.toString());
// 메세지 컨버터 동작 (UserDTO) ->> JSON 반환을 해서 ---> 클라이언트에 응답처리 한다.
return userDTO;
}
// @PutMapping("/put/demo1/{id}")
// public UserDTO putMethodName(@PathVariable(name = "id") String id) {
// System.out.println("id : " + id);
// // System.out.println("userDTO " + userDTO.toString());
// // 메세지 컨버터 동작 (UserDTO) ->> JSON 반환을 해서 ---> 클라이언트에 응답처리 한다.
// return null;
// }
}
💡 non-static inner classes
오류 원인 확인
비정적 내부 클래스
- 자바에서 비정적 내부 클래스는 외부 클래스의 인스턴스와 연결되어야만 인스턴스화 될 수 있다. 즉, 내부 클래스는 외부 클래스의 인스턴스가 필요하다.
- Jackson이 JSON 데이터를 객체로 변환할 때, 내부 클래스의 인스턴스를 생성하려 하지만, 비정적 내부 클래스는 외부 클래스의 인스턴스 없이는 생성할 수 없으므로 오류가 발생한다.
기본 생성자
- Jackson은 JSON 데이터를 자바 객체로 변환할 때, 기본 생성자(파라미터가 없는 생성자)를 사용해 객체를 생성한다. 하지만 비정적 내부 클래스는 외부 클래스의 참조를 필요로 하기 때문에, 기본 생성자를 생성 할 수 없다.
해결방법
- 내부 클래스를 정적(static)으로 변경
비정적 내부 클래스를 정적(static) 내부 클래스로 변경하면, 외부 클래스의 인스턴스 없이도 내부 클래스의 인스턴스를 생성할 수 있다.
2. 외부 클래스로 이동
내부 클래스를 별도의 외부 클래스로 이동시키는 방법도 있다. 이를 통해 Jackson이 객체를 생성할 때 문제없이 생성할 수 있다.
UserDTO 수정하기
package com.tenco.demo_v1.dto;
import java.util.List;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Data;
import lombok.Getter;
import lombok.ToString;
@Data
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserDTO {
private String name;
private Integer age;
//@JsonProperty("car_list")
private List<CarDTO> carList;
// 비 정적(static) 내부 클래스 (x)
// 스프링 부트 DTO 설계시 내부 클래스는 static 내부 클래스로 만들자
@Getter // 반드시 있어야 한다. !!!
@ToString
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
static class CarDTO {
private String name;
//@JsonProperty("car_number")
private String carName;
}
}
728x90
'Spring boot > Blog 프로젝트 만들기(JPA)' 카테고리의 다른 글
[Blog] 블로그 프로젝트 만들기 - 1 (REST API) (1) | 2024.10.01 |
---|---|
DELETE 방식에 이해 및 실습 (1) | 2024.09.30 |
단방향, 양방향 매핑에 대한 이해 (0) | 2024.09.30 |
영속성 컨텍스트란? (2) | 2024.09.30 |
엔티티 매니저에 대해 알아보자. (2) | 2024.09.30 |