HTTP Status Code 제어
HTTP Status Code를 서버에서 클라이언트 응답할 때, 가공해서 보낼 수 있다.
아래의 코드는 USER를 저장하기 위해 서버에 POST 요청 코드
- 서버에서 자동으로 USER id를 생성
- Client는 생성된 USER id를 알기 위해 서버한테 재요청 해야함
- 서버에서 응답할 때 상태 코드와, 생성된 id 값을 클라이언트에게 전송해주면 클라이언트가 재전송할 필요가 없어 네트워크 트래픽이 감소됌
예제 코드)
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user){
User savedUser = service.save(user);
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}") //반환 값은 가변 변수 id
.buildAndExpand(savedUser.getId()) //저장된 user값의 id값을 지정
.toUri(); //URI로 반환
return ResponseEntity.created(location).build();//서버로 부터 적절한 상태 코드를 보내주는 것이 좋은 api 임
}
POST로 전송결과, 상태코드는 201로 생성에 성공했음을 알수 있고, Header의 Location Value로 서버가 상태 코드와, 생성된 id를 클라이언트에게 응답으로 보내줌을 확인할 수 있다.
// 설계할 때 안좋은 케이스 하나가 클라이언트 모든 요청을 Post로 요청, 응답 코드를 200으로 처리하는 경우로, 예외 핸들링을 조합해서 사용해야 좋은 API 할 수 있다.
HTTP Status Code Exception Handling
서버에서는 존재하지 않은 id로 조회했을 때, 데이터를 조회할 수는 없으나 프로그램은 문제가 없어 200으로 응답한다.
존재하지 않은 id일 때 예외 처리하기,@ResponseStatus 상태 코드 제어
@GetMapping("/users/{id}")
public User retreiveAllUsers(@PathVariable int id) {
User user = service.findOne(id);
if(user == null){ //아이디가 존재하지 않을 때 예외를 발생시킨다.
throw new UserNotFoundException(String.format("ID[%s] not found",id));
}
return user;
}
@ResponseStatus 어노테이션으로 상태코드를 제어할수있다. 없으면 500에러로 출력
package com.example.restfulwebservice.User;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND) //not found인 404번 오류로 반환
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message); // 부모 클래스에서 전달 받은 메시지 실행
}
}
Spring AOP Exception Handling
AOP는 여러 객체에 공통으로 적용할 수 있는 기능을 분리해서 재사용성을 높여주는 기법이다. 공통적으로 사용하는 예외처리를 한곳으로 모아 사용 할수 있도록 Exception Handler을 구현한다.
- 예외 발생 시간, 오류 메시지, 오류 상세정보를 담아오는 객체 클래스 구현
package com.example.restfulwebservice.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExceptionResponse {
private Date timestamp; //오류 발생 시간
private String message; // 오류 메시지
private String details; // 오류 상세정보
}
-ExceptionHandler을 구현한다.
-컨트롤러가 실행하면 자동으로 핸들러가 실행되고 클래스 안에서 예외가 발생하면 hanlerAllExceptions메서드가 실행된다.
- 클래스 별로 예외 처리를 하고 싶으면, 해당 클래스로 @ExceptionHandler 해준다.
package com.example.restfulwebservice.exception;
import com.example.restfulwebservice.User.UserNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.util.Date;
@RestController
@ControllerAdvice
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(Exception.class) //모든 예외 처리
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request){
ExceptionResponse exceptionResponsee =
new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity(exceptionResponsee, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(UserNotFoundException.class) //해당 클래스에서 예외가 발생하면
public final ResponseEntity<Object> handleUserNotFoundExceptions(Exception ex, WebRequest request){
ExceptionResponse exceptionResponsee =
new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity(exceptionResponsee, HttpStatus.NOT_FOUND);
}
}
- @ControllerAdvice - 모든 컨트롤러가 실행될 때 자동 실행된다.
- ResponseEntityExceptionHandler는 Spring MVC에서 기본으로 제공되는 ExceptionHandler로 ControllerAdvice로 빈으로 등록해 모든 컨트롤러가 실행될 때 자동 실행되도록 한다.
Reference
인프런 강의 - Spring Boot를 이용한 RESTful Web Services 개발
'공부 > Spring Boot를 이용한 RESTful Web Services 정리' 카테고리의 다른 글
[Spring Boot] RESTful Service 기능 확장 - 유효성 Validation API(@valid) (0) | 2021.08.19 |
---|---|
[Spring Boot] DELETE HTTP Method 구현 (0) | 2021.08.19 |
[Spring Boot] API 구현- Domain , GET , POST 예제 (0) | 2021.08.04 |
[Spring Boot] DispatcherServlet 작동 원리, @PathVariable 사용법 (0) | 2021.08.03 |
[Spring boot] @RestController ,@GetMapping 예제 (0) | 2021.08.03 |