Spring
Spring Boot
Rest API

Rest API

Get

Hello
// RestAPI를 처리하는 Controller
@RestController
// 어떠한 주소를 받을지 지정
@RequestMapping("/api")
public class RestApiController {
    // Get Method 사용하기 위함
    @GetMapping(path = "/hello")
    public String hello(String[] args) {
        return "Hello Spring Boot";
    }
}

Path Variable

주소 내에 정보를 전달하는 방법 (User Id, Restaurant Id ... 등등)

// 파라미터에 들어갈 값은 중괄호{}에 넣어줘야 한다.
@GetMapping(path = "/echo/{message}")
public String echo(
        // 위에 쓰여진 {}에 들어간 파라미터 명이랑 동일한 이름이어야 한다.
        @PathVariable String message
) {
    System.out.println("echo message : " + message);
    return message;
}
  • annotation과 parameter명이 다른 경우
@GetMapping(path = "/echo_upper/{message}")
public String echo_upper(
        // 위에 {}에 쓰여진 이름과 다를 경우 name=""을 통해 어디에 매칭 시켜줄지 정할 수 있다.
        @PathVariable(name = "message") String msg
) {
    System.out.println("echo message : " + msg);
    return msg.toUpperCase();
}

다른 Type 넘겨주기

// http://localhost:8080/api/echo_upper/hi/age/500/isMan/false
@GetMapping(path = "/echo_upper/{message}/age/{age}/isMan/{isMan}")
public String echo_upper(
        // 위에 {}에 쓰여진 이름과 다를 경우 name=""을 통해 어디에 매칭 시켜줄지 정할 수 있다.
        @PathVariable(name = "message") String msg,
        @PathVariable int age,
        @PathVariable boolean isMan
) {
    System.out.println("echo message : " + msg);
    System.out.println("echo message : " + age);
    System.out.println("echo message : " + isMan);
 
 
    return msg.toUpperCase();
}

Query Parameter

특정 정보의 필터링을 걸 때 사용한다.
주소에는 대문자가 들어가면 안되고 두 개의 단어는 하이픈(-)을 사용해서 연결한다. (ex: issued-day)
?로 시작하고 이어주는 형태는 &로 묶어준다.

@GetMapping(path = "/book")
public void queryParam(
        // Query Parameter를 지정
        @RequestParam String category,
        @RequestParam String issuedYear,
        // Query Parameter를 어떤 이름으로 전달할지 지정
        @RequestParam(name = "issued-month")String issuedMonth ,
        @RequestParam(name = "issued_day")String issuedDay
)  {
    System.out.println(category);
    System.out.println(issuedYear);
    System.out.println(issuedMonth);
    System.out.println(issuedDay);
}

Model 이용

Model을 이용할 때는 model을 lombok을 이용해서 생성해주고 annotation을 따로 달지 않는다.

// Lombok을 사용할 때 쓰는 annotation
// getter, setter 자동 생성
@Data
// 전체 파라미터가 있는 Constructor
@AllArgsConstructor
// 파라미터가 없는 Constructor
@NoArgsConstructor
public class BookQueryParam {
    private  String category;
    private String issuedYear;
    private String issuedMonth;
    private String issuedDay;
}

Post

post로 값을 전달 받기 위해서는 PostMapping annotation을 사용해야 한다.
이 때, 변수는 반드시 객체여야하며, parameter 앞에 RequestBody annotation을 붙여줘야 한다. 이는 HTTP Body로 들어오는 데이터를 해당 객체에 Mapping 해주겠다는 얘기이다.

@PostMapping(path = "/post")
public BookRequest post(
        // Post는 기본적으로 객체를 받아야함
        // RequestBody : HTTP Body로 들어오는 데이터를 해당 객체에 Mapping을 해주겠다는 얘기
        @RequestBody BookRequest bookRequest
        ){
    System.out.println(bookRequest);
    return bookRequest;
}

Naming Convention

Json은 주로 snake_case를 사용하기 때문에 Json 요청을 보낼 때 camel case를 snake case로 변경해줘야 하는 경우가 생길 수 있다.
이럴 때 사용할 수 있는 annotation이 바로 PropertyNamingStrategies.SnakeCaseStrategy.class annotation이다.

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class User {
    private String userName;
    private int userPhoneNumber;
    private String userEmail;
}

아래 api 호출을 보면 java에서는 camel case로 parameter가 작성이 되었지만, 호출을 할 때는 snake_case를 사용하는 모습을 볼 수 있다.

  • userName -> user_name
  • userPhoneNumber -> user_phone_number
  • userEmail -> user_email

Put

리소스를 생성하고 리소스가 있다면 갱신한다.

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    private String userName;
    private int userPhoneNumber;
    private String userEmail;
    private boolean isKorean;
}

Json Primitive Error

위와 같이 변수명을 isKorean과 같은 형식으로 지정하게 되면 Data annotation이 setter를 생성할 때 setIsKorean이 아닌, setKorean으로 설정한다.
이는 Primitive type(기본형 타입)에서 is라는 시리즈는 boolean을 뜻하기 때문이다.
그래서 이를 Post에서 요청을 보낼 때 is_korean이라는 key에 true 값을 주게 되더라도 false를 출력하게 되는 것이다.


이를 해결하기 위한 방안은 2가지가 있다.

  1. 첫 번째 방법 : korean으로 보내기
  2. 두 번째 방법 : isKorean을 Reference type으로 변경한다.
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    private String userName;
    private Integer userPhoneNumber;
    private String userEmail;
    // boolean (Primitive Type) -> Boolean(Reference Type) 변경
    private Boolean isKorean;
}