Skip to content

Instantly share code, notes, and snippets.

@backpaper0
Last active May 29, 2019 21:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save backpaper0/e94cdd67b896571d8fce257a0521a4a0 to your computer and use it in GitHub Desktop.
Save backpaper0/e94cdd67b896571d8fce257a0521a4a0 to your computer and use it in GitHub Desktop.
A Study in Spring WebFlux

A Study in Spring WebFlux

リアクティブシステムとは

  • ノンブロッキング(InputStream/OutputStream → 非ブロックモードのChannel
  • バックプレッシャー
  • 非同期

参考:

Spring WebFluxとは……の前にSpring Web MVCは知っている?

  • 昔から存在するSpringのWebフレームワーク
  • サーブレットがベース
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String getHello() {
        return "Hello World";
    }

    @PostMapping("/hello")
    public Hello postHello(@RequestBody final YourName yourName) {
        return new Hello("Hello " + yourName.getName());
    }
}
public final class YourName {

    private final String name;

    public YourName(@JsonProperty("name") final String name) {
        this.name = Objects.requireNonNull(name);
    }

    public String getName() {
        return name;
    }
}
public final class Hello {

    private final String message;

    public Hello(@JsonProperty("message") final String message) {
        this.message = Objects.requireNonNull(message);
    }

    public String getMessage() {
        return message;
    }
}

Spring WebFluxとは

  • Spring Frameworkでリアクティブシステムを構築するためのWebフレームワーク
  • Reactor(Flux/Mono
  • Annotated ControllersとFunctional Endpoints

https://backpaper0.github.io/ghosts/reactive/

Annotated Controllers

@RestController
public class HelloController {

    @GetMapping("/hello")
    public Mono<String> getHello() {
        return Mono.just("Hello World");
    }

    @PostMapping("/hello")
    public Mono<Hello> postHello(@RequestBody final YourName yourName) {
        return Mono.just(yourName.getName())
                .map(name -> "Hello " + name)
                .map(Hello::new);
    }
}

Functional Endpoints

public class HelloHandler {

    public Mono<ServerResponse> getHello(final ServerRequest request) {
        return ServerResponse.ok().contentType(TEXT_PLAIN)
                .syncBody("Hello Functional World");
    }

    public Mono<ServerResponse> postHello(final ServerRequest request) {
        final var yourName = request.bodyToMono(YourName.class);
        final var hello = yourName
                .map(YourName::getName)
                .map(name -> "HELLO " + name)
                .map(Hello::new);
        return ServerResponse.ok().contentType(APPLICATION_JSON)
                .body(hello, Hello.class);
    }
}
@Configuration
public class HelloRouter {

    @Bean
    public RouterFunction<ServerResponse> routerFunction() {
        final var handler = handler();
        return route()
                .GET("/fn/hello", handler::getHello)
                .POST("/fn/hello", handler::postHello)
                .build();
    }

    @Bean
    public HelloHandler handler() {
        return new HelloHandler();
    }
}

ポイント

スレッドに強く関連付けたスタイルから、スレッドに依存しないスタイルへの転換

  • ThreadLocalでDBコネクションやHttpServletRequestを引回す、といった手法は捨て去る
  • 1リクエストを1トランザクションで囲む手法(トランザクションスクリプト)は捨て去る

手続き型プログラミングから、関数型プログラミングへの転換

  • forifを使ったコードから、高階関数を使ったコードへ
  • 処理をキューに追加して、空いているスレッドで順次処理していくため(処理が関数だとキューに追加しやすい)

関数型プログラミングの世界へ入門するには:

リンク

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment