From 5b662628c795b0d36d47635dcf89c9cc3cbae602 Mon Sep 17 00:00:00 2001 From: JoisFe Date: Tue, 5 Sep 2023 23:46:20 +0900 Subject: [PATCH 1/6] =?UTF-8?q?gradle=20=EB=A9=80=ED=8B=B0=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 65 ++++++++++++------- settings.gradle | 1 + springMvcHeadOffice/build.gradle | 11 ++++ .../SpringMvcHeadOfficeApplication.java | 11 ++++ .../SpringMvcBranchOfficeController.java | 34 ++++++++++ .../SpringMvcHeadOfficeController.java | 52 +++++++++++++++ .../src/main/resources/application.yml | 0 .../SpringwebfluxApplication.java | 13 ---- 8 files changed, 149 insertions(+), 38 deletions(-) create mode 100644 springMvcHeadOffice/build.gradle create mode 100644 springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/SpringMvcHeadOfficeApplication.java create mode 100644 springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcBranchOfficeController.java create mode 100644 springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java create mode 100644 springMvcHeadOffice/src/main/resources/application.yml delete mode 100644 src/main/java/com/example/springwebflux/SpringwebfluxApplication.java diff --git a/build.gradle b/build.gradle index 6879be0..dff4465 100644 --- a/build.gradle +++ b/build.gradle @@ -4,34 +4,49 @@ plugins { id 'io.spring.dependency-management' version '1.0.15.RELEASE' } -group = 'com.example' -version = '0.0.1-SNAPSHOT' - -java { - sourceCompatibility = '11' +repositories { + mavenCentral() } -configurations { - compileOnly { - extendsFrom annotationProcessor +subprojects { + apply plugin: 'java' + apply plugin: 'org.springframework.boot' + apply plugin: 'io.spring.dependency-management' + + group = 'com.example' + version = '0.0.1-SNAPSHOT' + + java { + sourceCompatibility = '11' } -} -repositories { - mavenCentral() -} + configurations { + compileOnly { + extendsFrom annotationProcessor + } + } -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-webflux' - compileOnly 'org.projectlombok:lombok' - developmentOnly 'org.springframework.boot:spring-boot-devtools' - annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'io.projectreactor:reactor-test' -} + configurations { + compileOnly { + extendsFrom annotationProcessor + } + } -tasks.named('test') { - useJUnitPlatform() -} + repositories { + mavenCentral() + } + + dependencies { + implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + developmentOnly 'org.springframework.boot:spring-boot-devtools' + annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + } + + tasks.named('test') { + useJUnitPlatform() + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 1b2bda0..044f7c2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,2 @@ rootProject.name = 'springwebflux' +include 'springMvcHeadOffice' \ No newline at end of file diff --git a/springMvcHeadOffice/build.gradle b/springMvcHeadOffice/build.gradle new file mode 100644 index 0000000..134c97c --- /dev/null +++ b/springMvcHeadOffice/build.gradle @@ -0,0 +1,11 @@ +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation 'org.projectlombok:lombok:1.18.20' + testImplementation 'io.projectreactor:reactor-test' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/SpringMvcHeadOfficeApplication.java b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/SpringMvcHeadOfficeApplication.java new file mode 100644 index 0000000..2932037 --- /dev/null +++ b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/SpringMvcHeadOfficeApplication.java @@ -0,0 +1,11 @@ +package com.example.springMvcHeadOffice; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringMvcHeadOfficeApplication { + public static void main(String[] args) { + SpringApplication.run(SpringMvcHeadOfficeApplication.class, args); + } +} diff --git a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcBranchOfficeController.java b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcBranchOfficeController.java new file mode 100644 index 0000000..2c8e1a6 --- /dev/null +++ b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcBranchOfficeController.java @@ -0,0 +1,34 @@ +package com.example.springMvcHeadOffice.controller; + +import java.awt.print.Book; +import java.util.Map; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@AllArgsConstructor +@RestController +@RequestMapping("/v1/books") +public class SpringMvcBranchOfficeController { + + private Map bookMap; + + /** + * HeadOffice 에서 bookId 를 통해 책을 조회하는 요청이 왔음 + */ + @ResponseStatus(HttpStatus.OK) + @GetMapping("/{book-id}") + public ResponseEntity getBook(@PathVariable("book-id") long bookId) throws InterruptedException { + // HeadOffice 요청을 처리하는 스레드가 차단되는지 BranchOffice 의 요청을 처리하는 스레드 5초를 sleep 하여 timeout 이 나는지 확인 + Thread.sleep(5000); + + Book book = bookMap.get(bookId); + + return ResponseEntity.ok(book); + } +} diff --git a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java new file mode 100644 index 0000000..d8525c5 --- /dev/null +++ b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java @@ -0,0 +1,52 @@ +package com.example.springMvcHeadOffice.controller; + +import java.awt.print.Book; +import java.net.URI; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +@Slf4j +@RequiredArgsConstructor +@RestController +@RequestMapping("/v1/books") +public class SpringMvcHeadOfficeController { + + private final RestTemplate restTemplate; + + URI baseUri = UriComponentsBuilder.newInstance().scheme("http") + .host("localhost") + .port(7070) + .path("v1/books") + .build() + .encode() + .toUri(); + + /** + * HeadOffice 에서 특정 bookId를 통해 책을 찾아달라는 요청을 받으면 + * RestTemplate 을 통하여 BranchOffice에 책을 찾아달라는 요청을 함 (Blocking I/O) + */ + @ResponseStatus(HttpStatus.OK) + @GetMapping("/{book-id}") + public ResponseEntity getBook(@PathVariable("book-id") long bookId) { + URI getBookUri = UriComponentsBuilder.fromUri(baseUri) + .path("/{book-id}") + .build() + .expand(bookId) + .encode() + .toUri(); // http://localhost:7070/v1/books/{book-id} + + ResponseEntity response = restTemplate.getForEntity(getBookUri, Book.class); + Book book = response.getBody(); + + return ResponseEntity.ok(book); + } +} diff --git a/springMvcHeadOffice/src/main/resources/application.yml b/springMvcHeadOffice/src/main/resources/application.yml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/springwebflux/SpringwebfluxApplication.java b/src/main/java/com/example/springwebflux/SpringwebfluxApplication.java deleted file mode 100644 index eb0b81e..0000000 --- a/src/main/java/com/example/springwebflux/SpringwebfluxApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.springwebflux; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringwebfluxApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringwebfluxApplication.class, args); - } - -} From 3007909058b507262d0e2ca2038d4ae2663d2333 Mon Sep 17 00:00:00 2001 From: JoisFe Date: Wed, 6 Sep 2023 21:35:27 +0900 Subject: [PATCH 2/6] =?UTF-8?q?Spring=20MVC=20=EA=B8=B0=EB=B0=98=20Blockin?= =?UTF-8?q?g=20I/O=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RestTemplate을 이용하여 Spring MVC 기반 Blocking I/O test - Gradle 멀티모듈로 구성하여 HeadOffice에서 BranchOffice로 도서 조회 요청하는 프로세스 통해 Blocking I/O test --- build.gradle | 1 + settings.gradle | 5 +- springMvcBranchOffice/build.gradle | 18 +++++++ .../SpringMvcBranchOfficeApplication.java | 29 ++++++++++ .../SpringMvcBranchOfficeController.java | 12 +++-- .../springMvcBranchOffice/domain/Book.java | 12 +++++ .../src/main/resources/application.yml | 2 + springMvcHeadOffice/build.gradle | 13 +++-- .../SpringMvcHeadOfficeApplication.java | 53 +++++++++++++++++++ .../SpringMvcHeadOfficeController.java | 2 +- .../example/springMvcHeadOffice/dto/Book.java | 11 ++++ .../src/main/resources/application.yml | 2 + 12 files changed, 151 insertions(+), 9 deletions(-) create mode 100644 springMvcBranchOffice/build.gradle create mode 100644 springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/SpringMvcBranchOfficeApplication.java rename {springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice => springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice}/controller/SpringMvcBranchOfficeController.java (79%) create mode 100644 springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/domain/Book.java create mode 100644 springMvcBranchOffice/src/main/resources/application.yml create mode 100644 springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/dto/Book.java diff --git a/build.gradle b/build.gradle index dff4465..7f603fd 100644 --- a/build.gradle +++ b/build.gradle @@ -39,6 +39,7 @@ subprojects { dependencies { implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-webflux' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' diff --git a/settings.gradle b/settings.gradle index 044f7c2..5960878 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,5 @@ rootProject.name = 'springwebflux' -include 'springMvcHeadOffice' \ No newline at end of file +include 'springMvcHeadOffice' +include 'springMvcHeadOffice' +include 'springMvcBranchOffice' + diff --git a/springMvcBranchOffice/build.gradle b/springMvcBranchOffice/build.gradle new file mode 100644 index 0000000..5de588b --- /dev/null +++ b/springMvcBranchOffice/build.gradle @@ -0,0 +1,18 @@ +plugins { + id 'java' +} + +version 'unspecified' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/SpringMvcBranchOfficeApplication.java b/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/SpringMvcBranchOfficeApplication.java new file mode 100644 index 0000000..e401977 --- /dev/null +++ b/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/SpringMvcBranchOfficeApplication.java @@ -0,0 +1,29 @@ +package com.example.springMvcBranchOffice; + +import com.example.springMvcBranchOffice.domain.Book; +import java.util.HashMap; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@Slf4j +@SpringBootApplication +public class SpringMvcBranchOfficeApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringMvcBranchOfficeApplication.class, args); + } + + @Bean + public Map bookMap() { + Map bookMap = new HashMap<>(); + + for (long i = 1; i <= 5; ++i) { + bookMap.put(i, new Book(i, "book" + i)); + } + + return bookMap; + } +} diff --git a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcBranchOfficeController.java b/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/controller/SpringMvcBranchOfficeController.java similarity index 79% rename from springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcBranchOfficeController.java rename to springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/controller/SpringMvcBranchOfficeController.java index 2c8e1a6..4a290f4 100644 --- a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcBranchOfficeController.java +++ b/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/controller/SpringMvcBranchOfficeController.java @@ -1,8 +1,8 @@ -package com.example.springMvcHeadOffice.controller; +package com.example.springMvcBranchOffice.controller; -import java.awt.print.Book; +import com.example.springMvcBranchOffice.domain.Book; import java.util.Map; -import lombok.AllArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -11,13 +11,17 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -@AllArgsConstructor @RestController @RequestMapping("/v1/books") public class SpringMvcBranchOfficeController { private Map bookMap; + @Autowired + public SpringMvcBranchOfficeController(Map bookMap) { + this.bookMap = bookMap; + } + /** * HeadOffice 에서 bookId 를 통해 책을 조회하는 요청이 왔음 */ diff --git a/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/domain/Book.java b/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/domain/Book.java new file mode 100644 index 0000000..06165e7 --- /dev/null +++ b/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/domain/Book.java @@ -0,0 +1,12 @@ +package com.example.springMvcBranchOffice.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class Book { + + private long id; + private String name; +} diff --git a/springMvcBranchOffice/src/main/resources/application.yml b/springMvcBranchOffice/src/main/resources/application.yml new file mode 100644 index 0000000..88137b8 --- /dev/null +++ b/springMvcBranchOffice/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 7070 \ No newline at end of file diff --git a/springMvcHeadOffice/build.gradle b/springMvcHeadOffice/build.gradle index 134c97c..5de588b 100644 --- a/springMvcHeadOffice/build.gradle +++ b/springMvcHeadOffice/build.gradle @@ -1,7 +1,14 @@ +plugins { + id 'java' +} + +version 'unspecified' + +repositories { + mavenCentral() +} + dependencies { - implementation 'org.springframework.boot:spring-boot-starter-webflux' - implementation 'org.projectlombok:lombok:1.18.20' - testImplementation 'io.projectreactor:reactor-test' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' } diff --git a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/SpringMvcHeadOfficeApplication.java b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/SpringMvcHeadOfficeApplication.java index 2932037..4200dd4 100644 --- a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/SpringMvcHeadOfficeApplication.java +++ b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/SpringMvcHeadOfficeApplication.java @@ -1,11 +1,64 @@ package com.example.springMvcHeadOffice; +import com.example.springMvcHeadOffice.dto.Book; +import java.net.URI; +import java.time.LocalDateTime; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; +@Slf4j @SpringBootApplication public class SpringMvcHeadOfficeApplication { + + private URI baseUri = UriComponentsBuilder.newInstance().scheme("http") + .host("localhost") + .port(8080) + .path("/v1/books") + .build() + .encode() + .toUri(); + public static void main(String[] args) { SpringApplication.run(SpringMvcHeadOfficeApplication.class, args); } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + + @Bean + public CommandLineRunner run() { + return (String... args) -> { + log.info("# 요청 시작 시간 : {}", LocalDateTime.now()); + + for (int i = 1; i <= 5; ++i) { + Book book = this.getBook(i); + log.info("{} : book name : {}", LocalDateTime.now(), book.getName()); // 5번 책 조회하니 약 25초 결과나옴 -> 스레드 차단확인! + } + }; + } + + private Book getBook(long bookId) { + RestTemplate restTemplate = new RestTemplate(); + + URI getBookUri = UriComponentsBuilder.fromUri(baseUri) + .path("/{book-id}") + .build() + .expand(bookId) + .encode() + .toUri(); // http://localhost:8080/v1/books/{book-id} + + ResponseEntity response = restTemplate.getForEntity(getBookUri, Book.class); + Book book = response.getBody(); + + return book; + } } diff --git a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java index d8525c5..a254540 100644 --- a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java +++ b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java @@ -1,6 +1,6 @@ package com.example.springMvcHeadOffice.controller; -import java.awt.print.Book; +import com.example.springMvcHeadOffice.dto.Book; import java.net.URI; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/dto/Book.java b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/dto/Book.java new file mode 100644 index 0000000..76953af --- /dev/null +++ b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/dto/Book.java @@ -0,0 +1,11 @@ +package com.example.springMvcHeadOffice.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +public class Book { + + private long id; + private String name; +} \ No newline at end of file diff --git a/springMvcHeadOffice/src/main/resources/application.yml b/springMvcHeadOffice/src/main/resources/application.yml index e69de29..47fbb02 100644 --- a/springMvcHeadOffice/src/main/resources/application.yml +++ b/springMvcHeadOffice/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 8080 \ No newline at end of file From 07f6edde29dd08f1d38dff38951d79448a7bafe0 Mon Sep 17 00:00:00 2001 From: JoisFe Date: Wed, 6 Sep 2023 22:32:32 +0900 Subject: [PATCH 3/6] =?UTF-8?q?Spring=20WebFlux=20=EA=B8=B0=EB=B0=98=20Non?= =?UTF-8?q?=20Blocking=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - WebClient를 이용하여 Spring WebFlux 기반 Non Blocking I/O test --- settings.gradle | 2 + .../SpringMvcBranchOfficeController.java | 2 +- .../SpringMvcHeadOfficeController.java | 13 ++-- .../example/springMvcHeadOffice/dto/Book.java | 1 - springReactiveBranchOffice/build.gradle | 18 ++++++ .../SpringReactiveBranchOffice.java | 27 ++++++++ .../SpringReactiveBranchOfficeController.java | 33 ++++++++++ .../domain/Book.java | 12 ++++ .../src/main/resources/application.yml | 2 + springReactiveHeadOffice/build.gradle | 18 ++++++ .../SpringReactiveHeadOfficeApplication.java | 64 +++++++++++++++++++ .../SpringReactiveHeadOfficeController.java | 49 ++++++++++++++ .../springReactiveHeadOffice/dto/Book.java | 10 +++ .../src/main/resources/application.yml | 2 + 14 files changed, 244 insertions(+), 9 deletions(-) create mode 100644 springReactiveBranchOffice/build.gradle create mode 100644 springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/SpringReactiveBranchOffice.java create mode 100644 springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/controller/SpringReactiveBranchOfficeController.java create mode 100644 springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/domain/Book.java create mode 100644 springReactiveBranchOffice/src/main/resources/application.yml create mode 100644 springReactiveHeadOffice/build.gradle create mode 100644 springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/SpringReactiveHeadOfficeApplication.java create mode 100644 springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/controller/SpringReactiveHeadOfficeController.java create mode 100644 springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/dto/Book.java create mode 100644 springReactiveHeadOffice/src/main/resources/application.yml diff --git a/settings.gradle b/settings.gradle index 5960878..e0d9bff 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,4 +2,6 @@ rootProject.name = 'springwebflux' include 'springMvcHeadOffice' include 'springMvcHeadOffice' include 'springMvcBranchOffice' +include 'springReactiveHeadOffice' +include 'springReactiveBranchOffice' diff --git a/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/controller/SpringMvcBranchOfficeController.java b/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/controller/SpringMvcBranchOfficeController.java index 4a290f4..c467c08 100644 --- a/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/controller/SpringMvcBranchOfficeController.java +++ b/springMvcBranchOffice/src/main/java/com/example/springMvcBranchOffice/controller/SpringMvcBranchOfficeController.java @@ -28,7 +28,7 @@ public SpringMvcBranchOfficeController(Map bookMap) { @ResponseStatus(HttpStatus.OK) @GetMapping("/{book-id}") public ResponseEntity getBook(@PathVariable("book-id") long bookId) throws InterruptedException { - // HeadOffice 요청을 처리하는 스레드가 차단되는지 BranchOffice 의 요청을 처리하는 스레드 5초를 sleep 하여 timeout 이 나는지 확인 + // HeadOffice 요청을 처리하는 스레드가 차단되는지 BranchOffice 의 요청을 처리하는 스레드 5초를 sleep 하여 시간 확인 Thread.sleep(5000); Book book = bookMap.get(bookId); diff --git a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java index a254540..7d896a0 100644 --- a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java +++ b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/controller/SpringMvcHeadOfficeController.java @@ -31,18 +31,17 @@ public class SpringMvcHeadOfficeController { .toUri(); /** - * HeadOffice 에서 특정 bookId를 통해 책을 찾아달라는 요청을 받으면 - * RestTemplate 을 통하여 BranchOffice에 책을 찾아달라는 요청을 함 (Blocking I/O) + * HeadOffice 에서 특정 bookId를 통해 책을 찾아달라는 요청을 받으면 RestTemplate 을 통하여 BranchOffice에 책을 찾아달라는 요청을 함 (Blocking I/O) */ @ResponseStatus(HttpStatus.OK) @GetMapping("/{book-id}") public ResponseEntity getBook(@PathVariable("book-id") long bookId) { URI getBookUri = UriComponentsBuilder.fromUri(baseUri) - .path("/{book-id}") - .build() - .expand(bookId) - .encode() - .toUri(); // http://localhost:7070/v1/books/{book-id} + .path("/{book-id}") + .build() + .expand(bookId) + .encode() + .toUri(); // http://localhost:7070/v1/books/{book-id} ResponseEntity response = restTemplate.getForEntity(getBookUri, Book.class); Book book = response.getBody(); diff --git a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/dto/Book.java b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/dto/Book.java index 76953af..1d51c2c 100644 --- a/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/dto/Book.java +++ b/springMvcHeadOffice/src/main/java/com/example/springMvcHeadOffice/dto/Book.java @@ -1,6 +1,5 @@ package com.example.springMvcHeadOffice.dto; -import lombok.AllArgsConstructor; import lombok.Getter; @Getter diff --git a/springReactiveBranchOffice/build.gradle b/springReactiveBranchOffice/build.gradle new file mode 100644 index 0000000..5de588b --- /dev/null +++ b/springReactiveBranchOffice/build.gradle @@ -0,0 +1,18 @@ +plugins { + id 'java' +} + +version 'unspecified' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/SpringReactiveBranchOffice.java b/springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/SpringReactiveBranchOffice.java new file mode 100644 index 0000000..148d899 --- /dev/null +++ b/springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/SpringReactiveBranchOffice.java @@ -0,0 +1,27 @@ +package com.example.springReactiveBranchOffice; + +import com.example.springReactiveBranchOffice.domain.Book; +import java.util.HashMap; +import java.util.Map; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class SpringReactiveBranchOffice { + + public static void main(String[] args) { + SpringApplication.run(SpringReactiveBranchOffice.class, args); + } + + @Bean + public Map bookMap() { + Map bookMap = new HashMap<>(); + + for (long i = 1; i <= 5; ++i) { + bookMap.put(i, new Book(i, "book" + i)); + } + + return bookMap; + } +} diff --git a/springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/controller/SpringReactiveBranchOfficeController.java b/springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/controller/SpringReactiveBranchOfficeController.java new file mode 100644 index 0000000..8c389ed --- /dev/null +++ b/springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/controller/SpringReactiveBranchOfficeController.java @@ -0,0 +1,33 @@ +package com.example.springReactiveBranchOffice.controller; + +import com.example.springReactiveBranchOffice.domain.Book; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@Slf4j +@RequestMapping("/v1/books") +@RestController +@AllArgsConstructor +public class SpringReactiveBranchOfficeController { + + private Map bookMap; + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/{book-id}") + public Mono getBook(@PathVariable("book-id") long bookId) throws InterruptedException { + // HeadOffice 요청을 처리하는 스레드가 차단되는지 BranchOffice 의 요청을 처리하는 스레드 5초를 sleep 하여 시간 확인 + Thread.sleep(5000); + + Book book = bookMap.get(bookId); + + return Mono.just(book); + } +} diff --git a/springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/domain/Book.java b/springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/domain/Book.java new file mode 100644 index 0000000..5483710 --- /dev/null +++ b/springReactiveBranchOffice/src/main/java/com/example/springReactiveBranchOffice/domain/Book.java @@ -0,0 +1,12 @@ +package com.example.springReactiveBranchOffice.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class Book { + + private long id; + private String name; +} diff --git a/springReactiveBranchOffice/src/main/resources/application.yml b/springReactiveBranchOffice/src/main/resources/application.yml new file mode 100644 index 0000000..13d1899 --- /dev/null +++ b/springReactiveBranchOffice/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 5050 \ No newline at end of file diff --git a/springReactiveHeadOffice/build.gradle b/springReactiveHeadOffice/build.gradle new file mode 100644 index 0000000..5de588b --- /dev/null +++ b/springReactiveHeadOffice/build.gradle @@ -0,0 +1,18 @@ +plugins { + id 'java' +} + +version 'unspecified' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/SpringReactiveHeadOfficeApplication.java b/springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/SpringReactiveHeadOfficeApplication.java new file mode 100644 index 0000000..4bba22b --- /dev/null +++ b/springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/SpringReactiveHeadOfficeApplication.java @@ -0,0 +1,64 @@ +package com.example.springReactiveHeadOffice; + +import com.example.springReactiveHeadOffice.dto.Book; +import java.net.URI; +import java.time.LocalDateTime; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.util.UriComponentsBuilder; +import reactor.core.publisher.Mono; + +@Slf4j +@SpringBootApplication +public class SpringReactiveHeadOfficeApplication { + + private URI baseUri = UriComponentsBuilder.newInstance().scheme("http") + .host("localhost") + .port(6060) + .path("/v1/books") + .build() + .encode() + .toUri(); + + public static void main(String[] args) { + System.setProperty("reactor.netty.ioWorkerCount", "1"); + SpringApplication.run(SpringReactiveHeadOfficeApplication.class, args); + } + + @Bean + public CommandLineRunner run() { + return (String... args) -> { + log.info("# 요청 시작 시간 : {}", LocalDateTime.now()); + + for (int i = 1; i <= 5; ++i) { + // Book book = this.getBook(i) 을 쓰지 않고 subscribe() 에서 응답 데이터를 전달받은 후에 처리 + // HeadOffice API 로부터 전달받은 응답이 Mono 타입이고 Mono 는 Reactor 에서 지원하는 Publisher 타입 중 하나이기 때문 + // Publisher 인터페이스 경우 subscribe() 를 호출하여 전달받은 데이터 처리하도록 정의 + // Mono 또한 Reactor 에서 지원하는 Publisher 타입 + this.getBook(i) + .subscribe( + book -> log.info("{} : book name: {}", LocalDateTime.now(), book.getName()) + ); + } + }; + } + + private Mono getBook(long bookId) { + URI getBookUri = UriComponentsBuilder.fromUri(baseUri) + .path("/{book-id}") + .build() + .expand(bookId) + .encode() + .toUri(); // http://localhost:6060/v1/books/{book-id} + + return WebClient.create() + .get() + .uri(getBookUri) + .retrieve() + .bodyToMono(Book.class); + } +} diff --git a/springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/controller/SpringReactiveHeadOfficeController.java b/springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/controller/SpringReactiveHeadOfficeController.java new file mode 100644 index 0000000..af29cc5 --- /dev/null +++ b/springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/controller/SpringReactiveHeadOfficeController.java @@ -0,0 +1,49 @@ +package com.example.springReactiveHeadOffice.controller; + +import com.example.springReactiveHeadOffice.dto.Book; +import java.net.URI; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.util.UriComponentsBuilder; +import reactor.core.publisher.Mono; + +@Slf4j +@RequestMapping("/v1/books") +@RestController +public class SpringReactiveHeadOfficeController { + + private URI baseUri = UriComponentsBuilder.newInstance().scheme("http") + .host("localhost") + .port(5050) + .path("/v1/books") + .build() + .encode() + .toUri(); + + @Autowired + public SpringReactiveHeadOfficeController() {} + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/{book-id}") + public Mono getBook(@PathVariable("book-id") long bookId) { + URI getBookUri = UriComponentsBuilder.fromUri(baseUri) + .path("/{book-id}") + .build() + .expand(bookId) + .encode() + .toUri(); // http://localhost:5050/v1/books/{book-id} + + return WebClient.create() + .get() + .uri(getBookUri) + .retrieve() + .bodyToMono(Book.class); + } +} diff --git a/springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/dto/Book.java b/springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/dto/Book.java new file mode 100644 index 0000000..2668cb2 --- /dev/null +++ b/springReactiveHeadOffice/src/main/java/com/example/springReactiveHeadOffice/dto/Book.java @@ -0,0 +1,10 @@ +package com.example.springReactiveHeadOffice.dto; + +import lombok.Getter; + +@Getter +public class Book { + + private long id; + private String name; +} \ No newline at end of file diff --git a/springReactiveHeadOffice/src/main/resources/application.yml b/springReactiveHeadOffice/src/main/resources/application.yml new file mode 100644 index 0000000..e92bb98 --- /dev/null +++ b/springReactiveHeadOffice/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 6060 \ No newline at end of file From 6ce194e6ddbfe2656b3a6526a7fb22f75a7a315f Mon Sep 17 00:00:00 2001 From: JoisFe Date: Thu, 7 Sep 2023 22:53:59 +0900 Subject: [PATCH 4/6] =?UTF-8?q?Hello=20Reactor=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=EC=9D=84=20=ED=86=B5=ED=95=9C=20Reactor=20=EC=95=8C=EC=95=84?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Flux를 이용한 데이터 생성하여 제공, 데이터 가공, 처리 3단계 알아보기 --- helloreactor/build.gradle | 18 ++++++++++++++++++ .../com/example/HelloreactorApplication.java | 17 +++++++++++++++++ settings.gradle | 1 + 3 files changed, 36 insertions(+) create mode 100644 helloreactor/build.gradle create mode 100644 helloreactor/src/main/java/com/example/HelloreactorApplication.java diff --git a/helloreactor/build.gradle b/helloreactor/build.gradle new file mode 100644 index 0000000..5de588b --- /dev/null +++ b/helloreactor/build.gradle @@ -0,0 +1,18 @@ +plugins { + id 'java' +} + +version 'unspecified' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/helloreactor/src/main/java/com/example/HelloreactorApplication.java b/helloreactor/src/main/java/com/example/HelloreactorApplication.java new file mode 100644 index 0000000..5438944 --- /dev/null +++ b/helloreactor/src/main/java/com/example/HelloreactorApplication.java @@ -0,0 +1,17 @@ +package com.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import reactor.core.publisher.Flux; + +@SpringBootApplication +public class HelloreactorApplication { + + public static void main(String[] args) { + SpringApplication.run(HelloreactorApplication.class, args); + + Flux sequence = Flux.just("Hello", "Reactor"); + sequence.map(String::toLowerCase) + .subscribe(System.out::println); + } +} diff --git a/settings.gradle b/settings.gradle index e0d9bff..3bd0581 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,4 +4,5 @@ include 'springMvcHeadOffice' include 'springMvcBranchOffice' include 'springReactiveHeadOffice' include 'springReactiveBranchOffice' +include 'helloreactor' From 435a8f43fe40682bad7e0353dce2e4cd624cfa3c Mon Sep 17 00:00:00 2001 From: JoisFe Date: Thu, 7 Sep 2023 22:54:44 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/example/HelloreactorApplication.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helloreactor/src/main/java/com/example/HelloreactorApplication.java b/helloreactor/src/main/java/com/example/HelloreactorApplication.java index 5438944..0117a2b 100644 --- a/helloreactor/src/main/java/com/example/HelloreactorApplication.java +++ b/helloreactor/src/main/java/com/example/HelloreactorApplication.java @@ -10,8 +10,8 @@ public class HelloreactorApplication { public static void main(String[] args) { SpringApplication.run(HelloreactorApplication.class, args); - Flux sequence = Flux.just("Hello", "Reactor"); - sequence.map(String::toLowerCase) - .subscribe(System.out::println); + Flux sequence = Flux.just("Hello", "Reactor"); // 데이터 생성 및 제공 + sequence.map(String::toLowerCase) // 데이터 가공 + .subscribe(System.out::println); // 전달받은 데이터 처리 } } From b3b427952a0df850e5d8c635ea07f4ad8382c5ce Mon Sep 17 00:00:00 2001 From: JoisFe Date: Sat, 9 Sep 2023 23:05:51 +0900 Subject: [PATCH 6/6] =?UTF-8?q?Marble=20Diagram=EC=9D=84=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20Reactor=20=EC=9D=B4=ED=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reactor 중 Mono, Flux의 이해 - Publisher의 여러 Operator 알아보기 --- marblediagram/build.gradle | 19 ++++++++ .../com/example/MarblediagramApplication.java | 12 +++++ .../main/java/com/example/mono/Example1.java | 14 ++++++ .../main/java/com/example/mono/Example2.java | 17 +++++++ .../main/java/com/example/mono/Example3.java | 47 +++++++++++++++++++ .../main/java/com/example/mono/Example4.java | 12 +++++ .../main/java/com/example/mono/Example5.java | 13 +++++ .../main/java/com/example/mono/Example6.java | 14 ++++++ .../main/java/com/example/mono/Example7.java | 16 +++++++ settings.gradle | 1 + 10 files changed, 165 insertions(+) create mode 100644 marblediagram/build.gradle create mode 100644 marblediagram/src/main/java/com/example/MarblediagramApplication.java create mode 100644 marblediagram/src/main/java/com/example/mono/Example1.java create mode 100644 marblediagram/src/main/java/com/example/mono/Example2.java create mode 100644 marblediagram/src/main/java/com/example/mono/Example3.java create mode 100644 marblediagram/src/main/java/com/example/mono/Example4.java create mode 100644 marblediagram/src/main/java/com/example/mono/Example5.java create mode 100644 marblediagram/src/main/java/com/example/mono/Example6.java create mode 100644 marblediagram/src/main/java/com/example/mono/Example7.java diff --git a/marblediagram/build.gradle b/marblediagram/build.gradle new file mode 100644 index 0000000..91f0175 --- /dev/null +++ b/marblediagram/build.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java' +} + +version 'unspecified' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'com.jayway.jsonpath:json-path:2.7.0' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/marblediagram/src/main/java/com/example/MarblediagramApplication.java b/marblediagram/src/main/java/com/example/MarblediagramApplication.java new file mode 100644 index 0000000..1b038e6 --- /dev/null +++ b/marblediagram/src/main/java/com/example/MarblediagramApplication.java @@ -0,0 +1,12 @@ +package com.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MarblediagramApplication { + + public static void main(String[] args) { + SpringApplication.run(MarblediagramApplication.class, args); + } +} diff --git a/marblediagram/src/main/java/com/example/mono/Example1.java b/marblediagram/src/main/java/com/example/mono/Example1.java new file mode 100644 index 0000000..786284c --- /dev/null +++ b/marblediagram/src/main/java/com/example/mono/Example1.java @@ -0,0 +1,14 @@ +package com.example.mono; + +import reactor.core.publisher.Mono; + +public class Example1 { + + /** + * Reactor 의 Publisher 타입 중 하나인 Mono 를 사용하여 문자열 출력 + */ + public static void main(String[] args) { + Mono.just("Hello Reactor") // 하나의 문자열! + .subscribe(System.out::println); + } +} diff --git a/marblediagram/src/main/java/com/example/mono/Example2.java b/marblediagram/src/main/java/com/example/mono/Example2.java new file mode 100644 index 0000000..eaa2a16 --- /dev/null +++ b/marblediagram/src/main/java/com/example/mono/Example2.java @@ -0,0 +1,17 @@ +package com.example.mono; + +import reactor.core.publisher.Mono; + +public class Example2 { + + public static void main(String[] args) { + Mono + .empty() // 데이터 한 건도 emit 하지 않음 + .subscribe( + none -> System.out.println("# emitted onNext Signal"), + error -> {}, + () -> System.out.println("# emitted onComplete Signal") + // 아무 데이터를 전송하지 emit 하지 않고 onComplete Signal 만을 전송 + ); + } +} diff --git a/marblediagram/src/main/java/com/example/mono/Example3.java b/marblediagram/src/main/java/com/example/mono/Example3.java new file mode 100644 index 0000000..317a99a --- /dev/null +++ b/marblediagram/src/main/java/com/example/mono/Example3.java @@ -0,0 +1,47 @@ +package com.example.mono; + +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import java.net.URI; +import java.util.Collections; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; +import reactor.core.publisher.Mono; + +public class Example3 { + + public static void main(String[] args) { + URI worldTimeUri = UriComponentsBuilder.newInstance().scheme("http") + .host("worldtimeapi.org") + .port(80) + .path("/api/timezone/Asia/Seoul") + .build() + .encode() + .toUri(); + + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + Mono.just( + restTemplate + .exchange(worldTimeUri, HttpMethod.GET, new HttpEntity(headers), String.class) + ) + .map(response -> { + DocumentContext jsonContext = JsonPath.parse(response.getBody()); + String dateTime = jsonContext.read("$.datetime"); + return dateTime; + }) + .subscribe( + data -> System.out.println("# emitted data: " + data), + error -> { + System.out.println(error); + }, + () -> System.out.println("# emitted onComplete signal") + ); + } +} diff --git a/marblediagram/src/main/java/com/example/mono/Example4.java b/marblediagram/src/main/java/com/example/mono/Example4.java new file mode 100644 index 0000000..08280f2 --- /dev/null +++ b/marblediagram/src/main/java/com/example/mono/Example4.java @@ -0,0 +1,12 @@ +package com.example.mono; + +import reactor.core.publisher.Flux; + +public class Example4 { + + public static void main(String[] args) { + Flux.just(6, 9, 13) + .map(num -> num % 2) + .subscribe(System.out::println); + } +} diff --git a/marblediagram/src/main/java/com/example/mono/Example5.java b/marblediagram/src/main/java/com/example/mono/Example5.java new file mode 100644 index 0000000..f014175 --- /dev/null +++ b/marblediagram/src/main/java/com/example/mono/Example5.java @@ -0,0 +1,13 @@ +package com.example.mono; + +import reactor.core.publisher.Flux; + +public class Example5 { + + public static void main(String[] args) { + Flux.fromArray(new Integer[]{3, 6, 7, 9}) + .filter(num -> num > 6) + .map(num -> num * 2) + .subscribe(System.out::println); + } +} diff --git a/marblediagram/src/main/java/com/example/mono/Example6.java b/marblediagram/src/main/java/com/example/mono/Example6.java new file mode 100644 index 0000000..ce24a81 --- /dev/null +++ b/marblediagram/src/main/java/com/example/mono/Example6.java @@ -0,0 +1,14 @@ +package com.example.mono; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public class Example6 { + + public static void main(String[] args) { + Flux flux = Mono.justOrEmpty("Steve") + .concatWith(Mono.justOrEmpty("Jobs")); + + flux.subscribe(System.out::println); + } +} diff --git a/marblediagram/src/main/java/com/example/mono/Example7.java b/marblediagram/src/main/java/com/example/mono/Example7.java new file mode 100644 index 0000000..468449b --- /dev/null +++ b/marblediagram/src/main/java/com/example/mono/Example7.java @@ -0,0 +1,16 @@ +package com.example.mono; + +import reactor.core.publisher.Flux; + +public class Example7 { + + public static void main(String[] args) { + Flux.concat( + Flux.just("Mercury", "Venus", "Earth"), + Flux.just("Mars", "Jupiter", "Saturn"), + Flux.just("Uranus", "Neptune", "Pluto") + ) + .collectList() + .subscribe(planets -> System.out.println(planets)); + } +} diff --git a/settings.gradle b/settings.gradle index 3bd0581..fb0e931 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,4 +5,5 @@ include 'springMvcBranchOffice' include 'springReactiveHeadOffice' include 'springReactiveBranchOffice' include 'helloreactor' +include 'marblediagram'