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);
}
}