반응형
이전 글: 2022.03.21 - [분류 전체보기] - [reactive] 7. CompletableFuture
저번 시간에 작성한 application을 webflux로 바꿔보는 작업을 진행한다.
springboot2.6.4로 진행하였기 때문에 유튜브와 다르게 아래의 의존성을 추가했다.
implementation 'org.springframework.boot:spring-boot-starter:2.6.4'
// implementation 'org.springframework.boot:spring-boot-starter-web:2.6.4'
implementation "org.springframework.boot:spring-boot-starter-webflux:2.6.4"
spring-webflux는 기본 서버가 netty라서 모두 네티로 작업하였다.
그리고 설정명이 달라서 수정하였다. 아래 소스를 참고!
@Slf4j
@EnableAsync
@SpringBootApplication
public class Application {
@RestController
public static class MyController{
@Autowired
MyService myService;
WebClient client = WebClient.create();
static final String URL1 = "http://localhost:8081/service?req={req}";
static final String URL2 = "http://localhost:8081/service2?req={req}";
@GetMapping("/rest")
public Mono<String> rest(int idx) {
//이것만으로는 api 쏘지 않음
Mono<ClientResponse> r = client.get()
.uri(URL1, idx)
.exchange();
//container안의 원소를 받아서 변환해서 다시 container(모노) 담아서 리턴 Mono<Mono<String>>
//이중으로 감싸주는 것은 원하는 결과가 아니니 flatmap으로 작업해서 하나로 합쳐야 함
Mono<String> body = r
.flatMap(clientResponse -> clientResponse.bodyToMono(String.class)) //Mono<String>
.doOnNext(c -> log.info(c))
.flatMap(res1 -> client.get().uri(URL2, res1).exchange()) //Mono<ClientResponse>
.flatMap(c -> c.bodyToMono(String.class)) //Mono<String>
.doOnNext(c -> log.info(c))
.flatMap(res2 -> Mono.fromCompletionStage(myService.work(res2))) //completable<String> -> mono<String>
.doOnNext(c -> log.info(c))
;
//return 시 모노면 그때 subscribe 수행함
//mono subscribe 를 spring이 실행해줌
return body;
}
}
@Service
public static class MyService{
//또다른 스래드 비동기 작업 시 async
@Async
public CompletableFuture<String> work(String req){
return CompletableFuture.completedFuture(req + "/asyncwork");
}
}
public static void main(String[] args) {
System.setProperty("reactor.netty.ioWorkerCount", "1");
System.setProperty("reactor.netty.pool.maxConnections", "2000");
SpringApplication.run(Application.class, args);
}
}
참고로 위 코드는 아래 코드를 수정한 것이다.
소스를 살펴보면 mono의 map과 flatmap의 사용 차이를 느낄 수 있을 것이다.
@GetMapping("/rest")
public Mono<String> rest(int idx) {
Mono<ClientResponse> r = client.get()
.uri(URL1, idx)
.exchange();
Mono<String> body = r
.flatMap(clientResponse -> clientResponse.bodyToMono(String.class)) //Mono<String>
.flatMap(res1 -> client.get().uri(URL2, res1).exchange()) //Mono<ClientResponse>
.flatMap(c -> c.bodyToMono(String.class)) //Mono<String>
.map(res2 -> myService.work(res2))
;
return body;
}
////////////////////////
@Service
public static class MyService{
public String work(String req){
log.info("myservice {}" , req);
return req + "/asyncwork";
}
}
map과 flatmap의 차이는 아래 링크에서 자세히 확인 가능하다. 스트림으로서의 차이는 이해했는데 동기/비동기에 대해서는 아직 잘 모르겠다.
https://www.geeksforgeeks.org/difference-between-map-and-flatmap-in-java-stream/
https://luvstudy.tistory.com/95
728x90
반응형
'개발 > reactive' 카테고리의 다른 글
[reactive] 10. Flux (0) | 2022.03.25 |
---|---|
[reactive] 9. Mono (0) | 2022.03.23 |
[reactive] 7. CompletableFuture (0) | 2022.03.21 |
[reactive] 6. refactoring (0) | 2022.03.21 |
[reactive] 5. 비동기 RestTemplate과 비동기 MVC/Servlet (0) | 2022.03.18 |