728x90
스프링 MVC를 이용한 REST-API 개발
- Jackson 라이브러리를 포함하고 있어, JSON 에 대한 처리에 대한 추가 설정이 필요없다.
- 명세에 필수/선택 여부가 반드시 정의되어야 한다.
- @ResponseBody → 스프링 MVC 의 View 를 사용하지 않는다.
- @RestController 를 사용하면, 응답값으로 리턴하는 객체는 마셜링된다.
- @RequestMappingHandlerMapping → @RequestMapping 으로 구현된 컨트롤러가 대상이면 사용,
- 사용자 요청과 핸들러를 매핑하는 정보를 관리
Controller 클래스 구현
- 스프링 빈으로 설정되어야 한다
- @PathVariable
- @RequestParam
- @RequestHeader
REST-API 응답 메시지 처리
- 엔티티 객체를 DTO 로 사용하는 것을 지양하자.
- ObjectMapper 는 멀티스레드 환경에서 안전하게 사용할 수 있다.
REST-API POST, PUT 매핑
- 메시지 바디의 JSON 을 처리하는 방법이 필요
- @RequestBody
- Content-Type 을 필수로 지정.
ResponseEntity 응답과 Pageable, Sort 클래스
- ResponseEntity
- Pageable 클래스
Pageable 자동 설정
- SpringDataWebAutoConfiguration : 웹 서포트 기능 자동 설정
- properties , yml 의 설정을 통해 쉽게 적용 가능
REST-API 검증과 예외 처리
- 클라이언트의 요청을 검증하기 위한 방법
- 사용자가 잘못된 형식의 값을 입력하거나 아예 입력하지 않아 null 값이 넘어오는 현상.
- JSR-303 스펙에서 제공하는 에너테이션을 사용하여 쉽고 빠르게 검증 ex ) @Notnull,
@Getter
@ToString
public class HotelRoomUpdateRequest {
@NotNull(message = "roomType can't be null")
private HotelRoomType roomType;
@NotNull(message = "originalPrice can't be null")
@Min(value = 0, message = "originalPrice must be larger than 0")
private BigDecimal originalPrice;
}
@Valid 애너테이션과 예제
- 검증할 자바 빈 객체를 마킹하는 용도로 사용
- 위의 @NotNull , @Min 등 과 같이 선언하기만 하면 동작하지 않고 @Valid 를 정의해야 동작한다.
- 컨틀롤러 클래스의 핸들러 메서드 인자에 설정 + BindingResult 객체 추가
- BindingResult 는 @Valid 를 붙인 객체 뒤에 선언해야 하는데, 복수 개일 경우 똑같이 복수개 선언해야 한다 .
@PutMapping(path = "/hotels/{hotelId}/rooms/{roomNumber}")
public ResponseEntity<HotelRoomIdResponse> updateHotelRoomByRoomNumber(
@PathVariable Long hotelId,
@PathVariable String roomNumber,
@Valid @RequestBody HotelRoomUpdateRequest hotelRoomUpdateRequest,
BindingResult bindingResult) {
- WebDataBinder 를 이용해서 Valid 기능 확장하기
- JSR-303 이 제공해주는 검증 기능이 명백하지 않고, 아래 (추가) 하는 과정이 번거로우면 Controller 에서 검증하는 것이 아닌 service 에서 검증하는 것 방법이 있다.
public class HotelRoomReserveValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return HotelRoomReserveRequest.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
HotelRoomReserveRequest request = HotelRoomReserveRequest.class.cast(target);
if (Objects.isNull(request.getCheckInDate())) {
errors.rejectValue("checkInDate", "NotNull", "checkInDate is null");
return;
}
if (Objects.isNull(request.getCheckOutDate())) {
errors.rejectValue("checkOutDate", "NotNull", "checkOutDate is null");
return;
}
if (request.getCheckInDate().compareTo(request.getCheckOutDate()) >= 0) {
errors.rejectValue("checkOutDate", "Constraint Error", "checkOutDate is earlier than checkInDate ");
return;
}
}
}
import javax.validation.Valid;
@RestController
public class HotelRoomReserveController {
private final ReserveService reserveService;
public HotelRoomReserveController(ReserveService reserveService) {
this.reserveService = reserveService;
}
@InitBinder
void initBinder(WebDataBinder binder) {
binder.addValidators(new HotelRoomReserveValidator());
}
@PostMapping(path = "/hotels/{hotelId}/rooms/{roomNumber}/reserve")
public ResponseEntity<HotelRoomIdResponse> reserveHotelRoomByRoomNumber(
@PathVariable Long hotelId,
@PathVariable String roomNumber,
@Valid @RequestBody HotelRoomReserveRequest reserveRequest,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
String errorMessage = new StringBuilder(bindingResult.getFieldError().getCode())
.append(" [").append(fieldError.getField()).append("] ")
.append(fieldError.getDefaultMessage())
.toString();
System.out.println("error : " + errorMessage);
return ResponseEntity.badRequest().build();
}
System.out.println(reserveRequest.toString());
Long reservationId = reserveService.reserveHotelRoom(
hotelId, roomNumber,
reserveRequest.getCheckInDate(),
reserveRequest.getCheckOutDate());
HotelRoomIdResponse body = HotelRoomIdResponse.from(reservationId);
return ResponseEntity.ok(body);
}
}
@ControllerAdvice 와 @ExceptionHandler 예외 처리 + @RestControllerAdvice
- 예외 처리 메커니즘은 견고한 시스템을 만드는데 반드시 필요하다.
- Unchecked Exception 과 checked Exception
- try - catch 와 throw
- @ExceptionHandler 는 controller 에 선언하는데, 선언된 예외만 처리할 수 있다. + @Controller 나 @ControllerAdvice 가 선언된 클래스에서만 동작.
- @ControllerAdvice 를 설정하면 해당 클래스는 전역 설정 스프링 빈이 된다.
- 스프링 애플리케이션 전체에서 예외 처리 메서드를 선언 할 수 있다.
- @RestCOntrollerAdvice = @ControllerAdvice + @ResponseEntity
- → HttpMessageConverter 로 인해 마셜링.
미디어 콘텐츠 내려받기
파일을 내려 받는 방법
- HttpMessageConverter 를 사용하여 메시지를 변환
- HttpServletResponse 를 사용해서 직접 OutputStream 을 다루는 방법
728x90
'Books' 카테고리의 다른 글
트렌드 코리아 2024 (0) | 2023.11.04 |
---|---|
스프링부트로 개발하는 MSA 컴포넌트 [7]장 (0) | 2023.08.26 |
스프링부트로 개발하는 MSA 컴포넌트 [1~4]장 (0) | 2023.08.20 |
비전공자를 위한 이해할 수 있는 IT 지식 을 읽고, (0) | 2023.01.03 |
일 잘하는 사람은 단순하게 합니다 를 읽고, (0) | 2022.12.12 |
댓글