Spring Boot

[Spring Boot]ResponseEntity

KrystalJo 2021. 11. 28. 23:44

ResponseEntity에 대하여 알아보기 전에 REST API에 대하여 알아보자. 아래글을 참고하였다.

https://meetup.toast.com/posts/92

 

REST API 제대로 알고 사용하기 : NHN Cloud Meetup

REST API 제대로 알고 사용하기

meetup.toast.com

 

REST API 설계 시 가장 중요한 항목 다음 2가지

  • URI는 정보의 자원을 표현해야 한다.
  • 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)

METHOD역할

POST POST를 통해 해당 URI를 요청하면 리소스를 생성합니다.
GET GET를 통해 해당 리소스를 조회합니다. 리소스를 조회하고 해당 도큐먼트에 대한 자세한 정보를 가져온다.
PUT PUT를 통해 해당 리소스를 수정합니다.
DELETE DELETE를 통해 리소스를 삭제합니다.

 

1) URI는 정보의 자원을 표현해야 한다. (리소스명은 동사보다는 명사를 사용)

    GET /members/delete/1

위와 같은 방식은 REST를 제대로 적용하지 않은 URI이다.

URI는 자원을 표현하는데 중점을 두어야 한다. delete와 같은 행위에 대한 표현이 들어가서는 안된다,.

 

2) 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE 등)로 표현

위의 잘못 된 URI를 HTTP Method를 통해 수정해 보면 아래의 형식이 된다.

    DELETE /members/1

 

 

ResponseEntity란?

public class RequestEntity<T> extends HttpEntity<T>
public class ResponseEntity<T> extends HttpEntity<T>

RequestEntity, ResponseEntity클래스는 HttpEntity클래스를 상속받는다.

 

ResponseEntity는 사용자의 HttpRequest에 대한 응답 데이터를 포함하는 클래스이다.

따라서 HttpHeader, HttpBody, HttpStatus를 포함한다.

 

 

ResponseEntity 클래스안에는 총 6개의 생성자가 존재한다.

private 생성자를 제외한 다른 생성자들은 모두 3개의 매개변수가 존재하는 private 생성자를 호출한다.

이 private 생성자가 HttpEntity의 객체변수와 자신의 전역변수를 가지고 초기화를 한 생성자이다.

public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) {
	this(body, headers, (Object) status);
}

public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, int rawStatus) {
	this(body, headers, (Object) rawStatus);
}

private ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, Object status) {
	super(body, headers);
	Assert.notNull(status, "HttpStatus must not be null");
	this.status = status;
}

 

결국 ResponseEntity의 생성자도 super()을 이용하여 HttpEntity의 생성자를 호출하여

응답데이터(ResponseData), 헤더(Header), 상태코드(Status)를 초기화한다.

 

public class HttpEntity<T> {

	public static final HttpEntity<?> EMPTY = new HttpEntity<>();

	private final HttpHeaders headers;

	@Nullable
	private final T body;
    
    
    .
    .
    .
    
	public HttpEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers) {
		this.body = body;
		this.headers = HttpHeaders.readOnlyHttpHeaders(headers != null ? headers : new HttpHeaders());
	}
}

 

 

 

TEST코드를 작성해보자.

 

1. Message를 담을 클래스

@Data
public class Message {

    private StatusEnum status;
    private String message;
    private Object data;

    public Message() {
        this.status = StatusEnum.BAD_REQUEST;
        this.data = null;
        this.message = null;
    }
}

 

 

2. 상태코드 클래스 Message클래스에 포함됨

public enum StatusEnum {

    OK(200, "OK"),
    BAD_REQUEST(400, "BAD_REQUEST"),
    NOT_FOUND(404, "NOT_FOUND"),
    INTERNAL_SERER_ERROR(500, "INTERNAL_SERVER_ERROR");

    int statusCode;
    String code;

    StatusEnum(int statusCode, String code) {
        this.statusCode = statusCode;
        this.code = code;
    }
}

 

3. RestController 클래스

@RestController
public class RestTestController {

    @GetMapping(value = "/rest")
    public ResponseEntity<Message> restTest(){
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("data1", "rest1");
        dataMap.put("data2", "rest2");
        dataMap.put("data3", "rest3");

        Message message = new Message();
        HttpHeaders headers= new HttpHeaders();
        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));

        message.setStatus(StatusEnum.OK);
        message.setMessage("성공 코드");
        message.setData(dataMap);

        return new ResponseEntity<>(message, headers, HttpStatus.OK);
    }
}

 

http://127.0.0.1:8080/rest GET 방식으로 요청이 들어오면 return값을 ResponseEntity<Message>로 생성하여

status, message, data를 전달해준다. 

 

 

@RestController
@RequestMapping("/replies/")
@Log4j2
@RequiredArgsConstructor
public class ReplyController {

    private final ReplyService replyService; //자동주입을 위해 final

    @GetMapping(value = "/board/{bno}", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<List<ReplyDTO>> getListByBoard(@PathVariable("bno") Long bno){
        log.info("bno : " + bno);

        return new ResponseEntity<>(replyService.getList(bno), HttpStatus.OK); // ResponseEntity가 json으로 만들어줌
    }

    @PostMapping("")
    public ResponseEntity<Long> register(@RequestBody ReplyDTO replyDTO){
        //@RequestBody은 JSON으로 들어오는 데이터를 자동으로 해당 타입의 객체로 메핑해주는 역할
        log.info(replyDTO);

        Long rno = replyService.register(replyDTO);

        return new ResponseEntity<>(rno, HttpStatus.OK);
    }


    @DeleteMapping("/{rno}")
    public ResponseEntity<String> remove(@PathVariable("rno") Long rno){
        log.info("RNO : " + rno);

        replyService.remove(rno);

        return new ResponseEntity<>("success", HttpStatus.OK);
    }

    @PutMapping("/{rno}")
    public ResponseEntity<String> modify(@RequestBody ReplyDTO replyDTO){
        log.info("replyDTO : " + replyDTO);

        replyService.modify(replyDTO);

        return new ResponseEntity<>("success", HttpStatus.OK);
    }
    
}

 

  1. getListByBoard - GET(/board/bno) : 조회
  2. register - POST() : 등록
  3. remove - DELETE(/rno) : 삭제
  4. modify - PUT(/rno) : 수정

-> REST API의 설계 규칙을 준수하여 작성하였다.

'Spring Boot' 카테고리의 다른 글

[Spring Boot] JPQL, Repository 확장  (0) 2021.11.07
[Spring Boot] Spring Data JPA  (0) 2021.10.23
[Spring Boot] RedirectAttributes, FlashAttributes  (0) 2021.10.01
[Spring Boot] Entity VS DTO  (0) 2021.09.25