SpringFramework/WebFlux

Spring Web Flux

lovineff 2020. 6. 8. 18:52

reactor3 API를 기본으로 사용하도록 되어있다.

MVC와 웹플러스를 공존해서 사용할 수 있도록 되어있다.

 

그러므로, 스프링 웹플럭스 프레임워크는 두가지 방식으로 개발이 지원된다.

- 어노테이션 방식

- 함수형 모델 형식

 

WebFlux는 아래와 같은 상황에서 사용하는게 좋다.

- 비동기 - 논블록 리액티브 개발

- 효율적으로 동작하는 고성능 웹 애플리케이션 개발

- 서비스간 호출이 많은 마이크로서비스 아키텍처에 적합

 

WebFlux는 ServerHttpRequest, ServerHttpResponse 객체를 사용한다.

HttpServletRequest, HttpServletResponse 객체를 사용하지 않음.

 

설정

Dependency 추가

implementation 'org.springframework.boot:spring-boot-starter-webflux'

 

응답 방식

  • Mono, Flux 타입으로 데이터를 응답해야 한다.

 

컨트롤러

MVC 패턴, 함수형 패턴을 모두 사용 가능하다.

MVC 패턴을 사용하고 내부 로직을 Reactor로 구성하는 것을 추천한다.

 

 

MVC 방식

// MainController.java
@RestController
public class MainController {
    @Autowired
    MainService mainService;

    @GetMapping("/")
    public Mono<String> main(){
        return Mono.just("test");
    }

    @GetMapping("/hello/{name}/{age}")
    public Mono<User> main(@PathVariable("name") String name,
                           @PathVariable("age") int age){
        return Mono.just(mainService.setUser(name, age));
    }

    @PostMapping("/post/user")
    public Mono<User> postUser(@RequestBody User user){
        return Mono.just(mainService.postSetUser(user));
    }
}


// MainService
public interface MainService {
    User setUser(String name, int age);
    User postSetUser(User user);
}


// MainServiceImpl
@Service
public class MainServiceImpl implements MainService{
    @Override
    public User setUser(String name, int age) {
        return User.builder()
                .name(name)
                .age(age)
                .build();
    }

    @Override
    public User postSetUser(User user) {
        String address = "판교 주소";

        return User.builder()
                .name(user.getName())
                .age(user.getAge())
                .address(address)
                .build();
    }
}

 

함수형 방식

// MainFunctionalConfiguration.java
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;

@Configuration
@EnableWebFlux
public class MainFunctionalConfiguration {
    @Bean
    public RouterFunction<ServerResponse> main(MainFunctionalHandler handler){
        return RouterFunctions.route(GET("/func"), handler::mainHandler);
    }

    @Bean
    public RouterFunction<ServerResponse> mainHello(MainFunctionalHandler handler){
        return RouterFunctions.route(GET("/func/{name}/{age}"), handler::mainHelloHandler);
    }
}

// MainFunctionalHandler.java
@Component
@RequiredArgsConstructor
public class MainFunctionalHandler {
    public Mono<ServerResponse> mainHandler(ServerRequest request){
        Mono<String> mono = Mono.just("hello");
        return ServerResponse.ok().body(mono, String.class);
    }

    public Mono<ServerResponse> mainHelloHandler(ServerRequest request){
        String name = request.pathVariable("name");
        int age = Integer.parseInt(request.pathVariable("age"));

        Mono<User> mono = Mono.just(User.builder().name(name).age(age).build());
        return ServerResponse.ok().body(mono, User.class);
    }
}