ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 애너테이션 기반 컨트롤러(Annotated Controller)
    Spring Reactive Web Application/Spring WebFlux 2023. 8. 26. 08:30
    반응형

      Spring WebFlux는 두 가지 프로그래밍 모델을 지원합니다. 하나는 애너테이션 기반 프로그래밍 모델이고, 다른 하나는 함수형 기반 프로그래밍 모델입니다. 이번 포스팅에서는 애너테이션 기반 컨트롤러에 대해, 다음 포스팅에서는 함수형 기반 프로그래밍 모델에 대해 정리합니다.

     

    Spring MVC 기반 Controller

      다음은 @RequestBody 애너테이션을 지정해서 클라이언트의 요청 데이터를 전달받고, ResponseEntity 클래스를 이용해 응답 데이터를 클라이언트에게 전달하는 전형적인 Spring MVC 기반 Controller 입니다.

    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    @RequestMapping("/v1/mvc/books")
    public class BookMvcController {
        private final BookMvcService bookMvcService;
        private final BookMvcMapper mapper;
    
        public BookMvcController(BookMvcService bookMvcService, BookMvcMapper mapper) {
            this.bookMvcService = bookMvcService;
            this.mapper = mapper;
        }
    
        @GetMapping("/{book-id}")
        public ResponseEntity getBook(@PathVariable("book-id") long bookId) {
            Book book = bookMvcService.findBook(bookId);
            return ResponseEntity.ok(mapper.bookToBookResponse(book));
        }
        
        @PostMapping
        public ResponseEntity postBook(@RequestBody BookDto.Post requestBody) {
            Book book = bookMvcService.createBook(mapper.bookPostToBook(requestBody));
            return ResponseEntity.ok(mapper.bookToBookResponse(book));
        }
    }

     

    Spring WebFlux 기반 Controller

      다음은 Spring MVC 기반의 Controller인 BookMvcController를 Spring WebFlux의 애너테이션 기반 프로그래밍 모델로 변경한 코드입니다. 핸들러 메서드 모두 Mono 타입을 리턴한다는 것 외에 변경된 부분이 거의 없습니다. 이처럼 애너테이션 기반 프로그래밍 모델은 기존 Spring MVC 구조와 거의 흡사하게 사용할 수 있습니다.

     

      Spring WebFlux에서는 리액티브 프로그래밍 라이브러리인 Reactor에서 제공하는 Mono를 사용합니다. 이 클래스는 제네릭(Generic)의 대상인 클래스를 비동기 스트리밍으로 반환합니다. 반환 횟수가 1회이면 Mono를 사용하고, 여러 번이면 Flux를 사용합니다.

    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.*;
    import reactor.core.publisher.Mono;
    
    @RestController("bookControllerV2")
    @RequestMapping("/v2/books")
    public class BookController {
        private final BookService bookService;
        private final BookMapper mapper;
    
        public BookController(BookService bookService, BookMapper mapper) {
            this.bookService = bookService;
            this.mapper = mapper;
        }
    
        @GetMapping("/{book-id}")
        public Mono getBook(@PathVariable("book-id") long bookId) {
            return bookService.findBook(bookId)
                    .flatMap(book -> Mono.just(mapper.bookToResponse(book)));
        }
        
        @PostMapping
        @ResponseStatus(HttpStatus.CREATED)
        public Mono postBook(@RequestBody Mono<BookDto.Post> requestBody) {
            Mono<Book> result = bookService.createBook(requestBody);
    
            return result.flatMap(book -> Mono.just(mapper.bookToResponse(book)));
        }
    }

     

      다음은 Mono<Book> 타입을 리턴하는 BookService 클래스입니다.

    import org.springframework.stereotype.Service;
    import reactor.core.publisher.Mono;
    
    import java.time.LocalDateTime;
    
    @Service("bookServiceV2")
    public class BookService {
        private final BookMapper mapper;
    
        public BookService(BookMapper mapper) {
            this.mapper = mapper;
        }
    
        public Mono<Book> findBook(long bookId) {
            return Mono.just(
                        new Book(bookId,
                                "Java 고급",
                                "Advanced Java",
                                "Kevin",
                                "111-11-1111-111-1",
                                "Java 중급 프로그래밍 마스터",
                                "2022-03-22",
                                LocalDateTime.now(),
                                LocalDateTime.now())
            );
        }
    
        public Mono<Book> createBook(Mono<BookDto.Post> book) {
            // not implement business logic;
            return book.flatMap(post -> Mono.just(mapper.bookPostToBook(post)));
        }
    }

     

    @ResponseBody, ResponseEntity

      Spring WebFlux는 Spring MVC에서 지원하던 @ResponseBody 애너테이션과 ResponseEntity 타입을 그대로 지원합니다. Spring MVC와의 차이점은 리액티브 타입을 이용해 데이터를 비동기적으로 response body에 렌더링되도록 한다는 것입니다.

     

      Spring WebFlux에서 지원하는 핸들러 메서드의 method argumentsreturn 타입을 알고 싶다면 아래 링크를 참고하시면 됩니다.

    https://docs.spring.io/spring-framework/reference/web/webflux/controller/ann-methods.html

     

    Handler Methods :: Spring Framework

    @RequestMapping handler methods have a flexible signature and can choose from a range of supported controller method arguments and return values.

    docs.spring.io

     

     

     

    [참고 정보]

    반응형

    'Spring Reactive Web Application > Spring WebFlux' 카테고리의 다른 글

    예외 처리  (0) 2023.09.16
    R2dbcEntityTemplate  (0) 2023.09.10
    Spring Data R2DBC  (0) 2023.09.09
    함수형 엔드포인트(Functional Endpoint)  (0) 2023.08.26
    Spring WebFlux 개요  (0) 2023.08.22

    댓글

Designed by Tistory.