Beim Java Day Tokyo 2017 hörte ich Reaktive Webanwendung von Spring Framework 5.0 und wurde etwas nervös, also Spring 5 Ich habe versucht, Spring WebFlux von hinzuzufügen.
Klicken Sie hier für Referenzmaterialien. First Spring WebFlux (Teil 1 - Versuchen Sie Spring WebFlux) Der Autor ist Toshiaki Maki, der mit dem Sprecher identisch ist. (Tatsächlich sagte er in der Sitzung etwas wie "Ich schreibe ein Blog. Wenn Sie es also lesen, können Sie es versuchen.")
Diesmal habe ich Spring Boot 2.0.0 M1 verwendet. (Weil Spring Boot Spring 5 ab 2.0.0 unterstützt)
Erstellen Sie es mit Spring Initializer. Stellen Sie die Spring Boot-Version auf 2.0.0 M1 ein und fügen Sie "Reactive Web" hinzu. (Übrigens Aktuator wird zum Zeitpunkt von M1 nicht unterstützt. Entschuldigung)
Also habe ich damit angefangen und bestätigt, dass Netty gestartet ist. Es ist vorerst in Ordnung. Unten finden Sie einen Auszug aus dem Startprotokoll.
2017-05-20 14:14:17.447 INFO 4880 --- [ restartedMain] o.s.w.r.r.m.a.ControllerMethodResolver : Looking for @ControllerAdvice: org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext@30361c29: startup date [Sat May 20 14:14:16 JST 2017]; root of context hierarchy
2017-05-20 14:14:17.916 INFO 4880 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2017-05-20 14:14:17.944 INFO 4880 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2017-05-20 14:14:18.241 INFO 4880 --- [ restartedMain] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2017-05-20 14:14:18.246 INFO 4880 --- [ restartedMain] itaka.demo.WebfluxSampleApplication : Started WebfluxSampleApplication in 2.181 seconds (JVM running for 3.946)
Wenn in WebFlux eine "@ Bean" wie "RouterFunction
//Ich habe einige statische Importe. Weitere Informationen finden Sie im Referenzmaterial.
@Bean
public RouterFunction<ServerResponse> routes() {
return route(GET("/"), req -> ok().body(Flux.just("Hello", "WebFlux"), String.class));
}
Wenn ich es starte und auf http: // localhost: 8080 /
zugreife, wird" Hello WebFlux "zurückgegeben.
das ist alles.
GET
oder POST
) wie zuvor als" {var} ".pathVariable ()
von ServerRequestSie können mit dem Verfahren von gehen.
@Bean
public RouterFunction<ServerResponse> routes() {
return RouterFunctions
.route(GET("/hello/{name}"), req ->
ok().body(Flux.just("Hello", req.pathVariable("name")), String.class));
}
Was passiert, wenn Sie sowohl das Routing der Pfadvariablen oben als auch das Routing der festen Pfaddefinition "/ hello / hoge" definieren? Aus der Schlussfolgerung geht hervor, dass dem ersten die Priorität eingeräumt wird. einfach.
RouterFunctions
.route(GET("/hello/{name}"), req -> ...)
.AndRroute(GET("/hello/hoge"), req -> ...);
-> Pfadvariable hat Priorität.
RouterFunctions
.route(GET("/hello/hoge"), req -> ...)
.AndRroute(GET("/hello/{name}"), req -> ...);
-> Feste Pfaddefinition hat Priorität.
Wenn es um den Maßstab des Beispiels geht, gibt es kein Problem, selbst wenn Sie die Routendefinition wie oben beschrieben verbinden. In der tatsächlichen Anwendung bedeutet dies jedoch, dass alle Zuordnungen in einer Controller-Klasse __ beschrieben sind Es ist also nicht gut. Daher können Sie ein wenig ordentlich schreiben, indem Sie die folgenden Schritte ausführen.
HelloRouter.java
@Component
public class HelloRouter {
private static final String PATH = "/hello";
public RouterFunction<ServerResponse> route() {
return RouterFunctions
.route(GET(PATH), this::hello)
.andRoute(GET(PATH + "/hoge"), this::helloHoge)
.andRoute(GET(PATH + "/{name}"), this::helloName);
}
private Mono<ServerResponse> hello(ServerRequest req) {
return ok().body(Flux.just("Hello", "WebFlux"), String.class);
}
private Mono<ServerResponse> helloName(ServerRequest req) {
return ok().body(Flux.just("Hello", req.pathVariable("name")), String.class);
}
private Mono<ServerResponse> helloHoge(ServerRequest req) {
return ok().body(Flux.just("Hoge", "Hoge"), String.class);
}
}
Hallo Router Route()Anruf
@Bean
public RouterFunction<ServerResponse> routes(HelloRouter helloRouter) {
return helloRouter.route();
}
Darüber hinaus können mehrere "RouterFunction
.and()Reiben mehrerer Routerfunktionen mit
//In StreamRouter"/strem"Es wird davon ausgegangen, dass das Routing von
@Bean
public RouterFunction<ServerResponse> routes(HelloRouter helloRouter, StreamRouter streamRouter) {
return helloRouter.route()
.and(streamRouter.route());
}
Dies legt das folgende Routing fest.
Kommentare Versuchen Sie also, den obigen Code mit "nest ()" weiter umzuschreiben. (Danke an Maki!)
RouterFunctions.nest()Hierarchische Routing-Definition
public RouterFunction<ServerResponse> routes() {
return nest(path("/hello"),
route(GET("/"), this::hello)
.andRoute(GET("/hoge"), this::helloHoge)
.andRoute(GET("/{name}"), this::helloName));
}
Übrigens habe ich auch statisch RouterFunctions.route ()
importiert, also war es sehr erfrischend!
Da Sie den Routing-Inhalt nur anhand des Router-Funktionsteils verstehen können, ist dies auch ein besserer Ort als die Definition in "@ Controller".
Das in ".body ()" von ServerResponse festgelegte "Flux" ist eine Klasse, die Publisher of Reactive Stream implementiert, und es scheint, dass Sie einen Creative Stream mit einem guten Gefühl realisieren können.
Lassen Sie uns als konkretes Beispiel etwas implementieren, das "beim Zugriff endlos zurückgegeben und die Zahlen hochgezählt werden". Die Methode ist wie folgt.
@Bean
public RouterFunction<ServerResponse> routes() {
Stream<Integer> stream = Stream.iterate(0, i -> i + 1);
Flux<Integer> flux = Flux.fromStream(stream).delayElements(Duration.ofSeconds(1));
return RouterFunctions
.route(GET("/stream"), req ->
ok().contentType(MediaType.APPLICATION_STREAM_JSON).body(flux, Integer.class));
}
Wenn Sie jetzt auf "http: // localhost: 8080 / stream" zugreifen, fließen die Zahlen endlos. Da es jedoch so ist, fließt es mit großer Dynamik. Im obigen Beispiel wird ".delayElements ()" verwendet, um es mit einem Intervall fließen zu lassen.
Während ich "try WebFlux" sagte, experimentierte ich mehr als die Hälfte mit Router-Funktionen. Um "Web Flux ist erstaunlich" zu erleben, scheint es besser, eine Anwendung zu erstellen, die als kompliziert oder "superschnell, weil sie nicht blockiert" verstanden werden kann.
Router-Funktionen waren aufregender als beim Anhören der Java Day Tokyo-Sitzung. Diesmal habe ich nur "GET" verwendet, aber natürlich können auch andere HttpMethods verwendet werden, und komplexe Routing-Bedingungen können mit ".and ()", ".or ()", ".negate ()" usw. erstellt werden. Es sieht lustig aus, weil du es auch kannst. Im Moment (Spring Boot 2.0.0) scheint es jedoch nicht mit "@ Controller" koexistieren zu können, so dass es ein wenig schwierig ist, es auf vorhandene Anwendungen anzuwenden (alle müssen neu geschrieben werden). Wenn Sie es tun, sollten Sie es mit einer neuen Anwendung tun.
Der Code von dem, was ich dieses Mal versucht habe, ist wie folgt. (Da ich beim Schreiben überarbeitet habe, gibt es eine leichte Abweichung vom Code in diesem Artikel.) IsaoTakahashi/webflux-sample - GitHub
Recommended Posts