티스토리 뷰
API에 관련된 POST, GET, PUT, DELETE 등이 있다. 이때 응답을 하는 방식에 대해 알아보자. 기본적으로는 요청을 받아야 응답을 줄수있다.
프로젝트 생성
> dependencies는 sping web으로 하자.(Gradle, java11, jar)
기본적으로는 요청을 받아야 응답을 줄수있다.따라서 기본적으로 controller라는 이름으로 패키지를 만들어주고, 그 안에 ApiController라는 class를 넣어준다. 그리고 @RestController와 @RequestMapping을 추가해주고 우선은 문자열을 받아서 확인하는 코드를 작성해보자.
방법1_text를 리턴하기
위와 같이 적어준다. 그리고 api를 아래와 같이 보내면 결과가 뜨는 것을 확인 할 수 있다.
위의 방식과 같이 text를 리턴해주는 방식은 거의 안쓴다.
방법2_JSON을 리턴하기
우선은 @RequestBody에서 User를 사용할 것이라 dto 패키지를 만들고 그 안에 User라는 class를 만들자. User에는 리턴하고 싶은 데이터를 적어주자.
User에는 리턴하고 싶은 변수를 우선적으로 적어준다. 그리고 get set 메서드를 적용한다.
이런식으로 User 클래스를 만들었다. 그리고 아래는 tos 를 적고 엔터를 눌러 오버라이딩 까지 적었다. 완성 클래스는 아래와 같다.
package com.example.response.dto;
public class User {
private String name;
private int age;
private String phoneNumber;
private String address;
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;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", phoneNumber='" + phoneNumber + '\'' +
", address='" + address + '\'' +
'}';
}
}
이제 Controller의 ApiController도 작성을 해보자.
package com.example.response.controller;
import com.example.response.dto.User;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class ApiController {
// TEXT
@GetMapping("/text")
public String text(@RequestParam String account){
return account;
}
// JSON
@PostMapping("/json")
public User json(@RequestBody User user){
return user;
}
}
Json 코드의 첫번째 줄을 보면 User를 @RequestBody로 받아서 User를 리턴 한 것을 알 수 있다.
기본적인 로직은 request가 오게되면 object mapper를 통해서 object로 우선 바뀐다. 그리고 우리가 작성한 method를 통과한 후에 object를 다시 return한다. 그러면 object mapper를 통해 json으로 바꿔지고 reponse가 들어간다.
우리는 Json을 받기 위해 만든것이다. 그리고 @RequestBody User에서 User를 활성화 시키려면 커서를 User로 이동하고 alt+enter를 눌러서 dto.user를 선택하면 import를 가져오는 것을 알 수 있다. 그리고 아래의 JSON 디자인에 넣을 내용을 참고하려면 User를 ctrl+클릭하면 User 클래스로 이동하게 된다.
JSON디자인
> 여기서 주의할 점은 phoneNumber는 camelCase이다.
{
"name" : "steve",
"age" : 10,
"phoneNumber" : "010-0000-0000",
"address" : "패스트캠퍼스"
}
이런식으로 response가 오는 것을 확인할 수 있다. 보면 JSON을 카멜케이스로 넣었기 때문에 문제 없이 잘 작동하는 것을 알 수 있다.
Response 변경하기
> 앞에서 request를 변경하는 것과 비슷하다.
1. @JsonProperty("phone_number")
2. @JsonNaming(value = PeopertyNamingStrategy.SnakeCaseStrategy.class)
2번으로 하면 되고, 특이한 부분은 1번으로 지정해주면된다. 이거 2가지만 알면 API를 사용하는데 지장이 없다.
응답 확인하기
> 보통 우리가 위에서 작성한 코드는 아래와 같이 200응답을 준다.
@PostMapping("/json")
public User json(@RequestBody User user){
return user; //200 ok
}
> put은 리소스 생성 시 201을 준다. 즉, 200과 201을 둘다 쓴다. 201을 내리는 방법은 아래와 같다.
- ResponseEntity라는 객체에 아래와 같이 제네릭타입을 <>로 설정해 주면 된다.
- .status에서 201에 대한 코드를 확인 할 수 있다. HttpStatus.CREATED에 ctrl+클릭 해서 들어가보면 201을 주는 것을 알 수 있다.
- .body에는 user 객체를 body에 담아서 보내는 것을 알 수 있다.
정리하면, Http status코드를 지정가능하다. body에 데이터도 넣어줄 수 있다. 이때 넣어준 데이터는 object mapper를 통해 json으로 변경되서 내려간다. 그리고 필요 시 header값도 넣어줄 수 있다. 응답에 대해 커스터 마이징이 필요하다면 ResponseEntity를 사용하면 된다. 관련 값을 명확하게 값을 만들어 주는 것이 좋다.
위의 CREATED 부분을 ctrl+클릭을 해보면 아래와 같이 사용가능한 것들을 확인가능하다.
보면 OK를 적으면 2--이 나오고, CREATED를 적으면 201이 나오는 것을 확인 할 수 있다. 이러한 것들을 잘 확인해서 적용해 주면 된다.
요청을 보내보면 응답이 201로 오는 것을 확인 할 수 있다.
Controller annotation
> 지금까지는 RestController를 사용했다. 그러나 HTML 파일을 리턴하는 컨트롤러를 확인해보자. PageController라는 class를 만들자
- @Controller라는 annotation을 사용할 것이다.
작성 클래스 위치와 코드는 위의 사진을 참고하자.
html파일은 src/main/resources/static안에 main.html을 만들어주자. 대략적인 구조와 방식은 아래의 사진과 같다.
get 방식으로 요청을 보내보자
200 OK가 response로 온 것을 알 수 있고, content-type도 html로 잘 온 것을 확인할 수 있다.
정리하면 API를 리턴을 하는 것 뿐만 아니라 page를 리턴하는 것도 작성이 가능하다. 이 때 아래와 같이 리턴자체가 String이 되면 자동으로 html 파일을 찾아가게 된다.
@Controller
public class PageController {
@RequestMapping("/main")
public String main(){
return "main.html";
}
}
Controller에서도 JSON을 내려주는 방식이 있다.
1. @ResponseEntity
2. @ResponseBody
(import는 alt+enter를 눌러주면 된다.)
@Controller는 String을 리턴하면 리소스를 찾게 되지만, 아래와 같이 @ResponseBody를 붙여주면, 객체 자체를 return했을 떄 리소스를 찾지 않고, Response의 Body를 만들어서 return해 준다.
package com.example.response.controller;
import com.example.response.dto.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class PageController {
@RequestMapping("/main")
public String main(){
return "main.html";
}
@ResponseBody
@GetMapping("/user")
public User user(){
// User user = new User(); //구버전, User가 아닌 긴이름의 클래스는 적기 불편..
var user = new User(); // 자바 11버전을 쓰고있다. 11부터는 이런식으로 타입추론 가능
user.setName("hanpy");
user.setAddress("강남");
return user;
}
}
자바 구 버전 같은 경우는 var을 쓰면 안된다. 위와 같이 적고 요청을 보내보자.
아래와 같이 응답이 Body부분에 잘 담겨 오는 것을 확인 할 수 있다. 기본적으로 phoneNumber를 안 넣었으니 null이 된다. 그리고 age는 0으로 왔다.
우리가 변수를 지정한 부분을 보자. String은 디폴트값이 null이다. 그러나 int는 디폴트 값이 0이기 때문에 age를 적지 않아도 0값이 return되는 것을 확인 할 수 있다.
만약 null로 변경하고 싶으면, int를 Integer로 모두 변경해 준다. object 매서드는 get매서드를 보기 때문에 아래부분의 getAge부분도 수정해 줘야한다.
이러한 식으로 int를 Integer로 변경해 줬다.
그러면 0이 아닌 null로 age가 잘 들어오는 것을 알 수 있다.
여기서 우리는 null값을 포함 시키지 않는 방법도 있다.
1. @JsonInclude 를 사용한다. 이것은 어떠한 값을 포할 시킬 것인지를 적는 것이다.
2. @JsonInclude(JsonInclude.Include.NON_NULL) : Null을 포함시키지 않겠다
3. @JsonInclude(JsonInclude.Include.NON_EMPTY) : 빈값을 포함시키지 않겠다
이런식으로 작성하고 요청을 보내주면 아래와 같이 있는 값들만 나타난다.
이러한 것들은 JSON규격을 정할 때 정해주면 되고, 확인하고 맞춰서 개발을 해주면된다. 전체 코드는 아래와 같다.
package com.example.response.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
private String name;
private Integer age;
private String phoneNumber;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", phoneNumber='" + phoneNumber + '\'' +
", address='" + address + '\'' +
'}';
}
}
보통은 @JsonInclude(JsonInclude.Include.NON_NULL) 이렇게 안적고 디폴트로 쓴다. 다만, Null 처리가 힘든경우가 생기거나 할 때 빼고 보내주는 방법을 사용하기도 한다.
정리하면 @ResponseBody를 통해 내려주게 되면 html 리소스를 찾는 것이 아니라 Json을 내려주기가 가능하다. 보통은 우리가 Rest API를 많이 개발하기 때문에 따로 컨트롤러를 사용하기 보다는 초기에 배운 @RestController를 만들어서 사용하면, 굳이 @ResponseBody를 안쓴다.
즉, 페이지 컨트롤을 할 때만 @Controller를 사용하고, API관련은 @RestController로 사용하면 된다.
'Platform > spring boot' 카테고리의 다른 글
[spring boot] Object Mapper (0) | 2021.06.21 |
---|---|
[intellij] OpenJDK 64-Bit Server VM warning (0) | 2021.06.20 |
[spring boot] PUT API 방식 (0) | 2021.06.15 |
[spring boot] POST 방식 (0) | 2021.06.13 |
[spring boot] 8080 포트 변경 (0) | 2021.06.08 |
- Total
- Today
- Yesterday
- react
- Vue
- read_csv
- DFS
- UserCreationForm
- Express
- Python
- Deque
- TensorFlow
- next.config.js
- JavaScript
- 자연어처리
- nodejs
- 자료구조
- nextjs autoFocus
- BFS
- error:0308010C:digital envelope routines::unsupported
- Queue
- django
- login
- mongoDB
- useHistory 안됨
- vuejs
- react autoFocus
- useState
- 클라우데라
- typescript
- logout
- NextJS
- pandas
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |