1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Spring5 新特性之 webflux

        共 15683字,需瀏覽 32分鐘

         ·

        2021-08-11 03:05

        議題:

        • 為什么要使用 Web Flux

        • 從 Web MVC 過度到 Web Flux

        • 函數(shù)式 Endpoint

        為什么要使用 Web Flux

        • 非阻塞編程

          • NIO

          • Reactive

        • 函數(shù)式編程

          • Lambda

          • Kotlin

        從 Web MVC 過度到 Web Flux

        • Annotation Controller

        • WebFlux 配置

        • Reactor 框架

        函數(shù)式 Endpoint

        • HandlerFunction

        • RouterFunction

        Spring MVC 可以直接遷移到 Spring WebFlux 。

        現(xiàn)在很多人都在用 Web MVC ,很少用 WebFlux,函數(shù)式 Endpoint。

        編程模型沒有很多的更新。NIO 是 非阻塞式 I/O ,在 JAVA 7 里邊,增加了一個 AIO 的概念,增加了一個并行,增加了異步的方式,

        https://github.com/reactive-streams/reactive-streams-jvm

         Reactive-Stream 是一種編程模型,編程規(guī)范,Spring Cloud 里邊 hystrix 就是基于 RxJava 的,RxJava 就是 Reactive 的拓展,現(xiàn)在用的不是特別多,在安卓用的比較多。

        Web on Reactive Stack

        Why was Spring WebFlux created?

        Part of the answer is the need for a non-blocking web stack to handle concurrency with a small number of threads and scale with fewer hardware resources. Servlet 3.1 did provide an API for non-blocking I/O. However, using it leads away from the rest of the Servlet API, where contracts are synchronous (FilterServlet) or blocking (getParametergetPart). This was the motivation for a new common API to serve as a foundation across any non-blocking runtime. That is important because of servers (such as Netty) that are well-established in the async, non-blocking space.

        Part of the answer is the need for a non-blocking web stack to handle concurrency with a small number of threads and scale with fewer hardware resources.

        非阻塞的 web 的技術(shù)棧,同時來處理并行的一些東西,不是理由的理由,把大多數(shù)開發(fā)人員當成 250 在耍,Tomcat 8 以后,一種是 BIO,一種是 NIO, -8080BIO 中綴,就是 Tomcat 6 或者 Tomcat 7 的版本,就是 Tomcat 8 中就有了非阻塞式的編程了,問題的關(guān)鍵在于什么地方是阻塞,什么地方是應該所謂的并發(fā)去處理,在 Servlet 3.1 中已經(jīng)給一種異步的編程方式。

        示例:
        1

        request 先發(fā)起來的一種 AsyncContext 異步的上下文,相應的處理的方式,它是有一種監(jiān)聽器,

        #onComplete()、#onTimeout()#onError()、#onStartAsync() 四種狀態(tài)和 Reactive 有一些類似

        1
        2
        3
        4
        5
        6
        public interface Subscriber<T> {
        public void onSubscribe(Subscription s);
        public void onNext(T t);
        public void onError(Throwable t);
        public void onComplete();
        }

        訂閱者,這是一個訂閱者, Sevlet 3.0 就開始了異步了。很多技術(shù)都有一種哲學上的東西。

        異步的時候,就是開啟一個線程池,Servlet 3.0 里邊異步的方式用的非常少,大多數(shù)的時候,都用的是自己寫個線程池,或者用 Spring MVC 寫一個線程池,

        就是 NIO,

        Async-web 項目:

        1
        http-nio-8080-exec-1 開始執(zhí)行!http-nio-8080-exec-2 執(zhí)行中!http-nio-8080-exec-3 執(zhí)行完成

        它是不是阻塞和非阻塞,是你自己去權(quán)衡的,阻塞,非阻塞都是同步的,如果不是同步的話,就會遇到線程安全的問題,我們以前遇到的 ThreadLocal ,spring MVC 用到了很多 ThreadLocal

        org.springframework.web.context.request.RequestContextHolder
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) {
        if (attributes == null) {
        resetRequestAttributes();
        }
        else {
        if (inheritable) {
        inheritableRequestAttributesHolder.set(attributes);
        requestAttributesHolder.remove();
        }
        else {
        requestAttributesHolder.set(attributes);
        inheritableRequestAttributesHolder.remove();
        }
        }
        }
        org.springframework.web.context.request.ServletRequestAttributes
        1
        2
        3
        4
        5
        6
        7
        8
        private static final boolean jsfPresent =
        ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader());

        private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
        new NamedThreadLocal<>("Request attributes");

        private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =
        new NamedInheritableThreadLocal<>("Request context");

        把你的請求放到這里來了,他使用的 ThreadLocal ,ThreadLocal 你是同一個線程的時候使用,如果不是同一個線程使用的話,就會出現(xiàn)相應的問題。

        我們的 開始,結(jié)束,超時,錯誤,事件回調(diào)的時候,會把我們每個操作的線程名稱打印出來,意味著,當每個方法被回調(diào)的時候,它會他的請求打印出來,線程池里邊的序號不是一一對應的。它執(zhí)行中的時候呢,有一個異步的過程,那么這是它一個異步的特點,但是這個異步的特點并不能說明它是一個非阻塞的異步。只能說明它是一個異步。這是 Sevlet 3.0 的一個規(guī)范,

        Spring 官網(wǎng):

        Servlet 3.1 提供了一種 Non-blocking I/O,

        軟件架構(gòu)怎么怎么搞,Dubbo ? Zookeeper ? Framework ? 不能只了解源碼,需要了解源碼的背后它很多很多的哲學上的東西,Tomcat 8 的里邊已經(jīng)是 非阻塞式IO 了,基于事件的,非阻塞 不代表它不阻塞,這是 多工 的意思 ,嚴格意義上阻塞是同步的意思。一個 CPU 執(zhí)行一條命令的時候,它是一個一個執(zhí)行的,那么非阻塞的時候呢,無非是我一個 CPU 在輪詢的時候,同一個CPU 可以執(zhí)行多個指令,并不能代表它是異步的,

         并行 和 并發(fā) 到底什么區(qū)別?并行是 同時 干 若干個事情,并發(fā),是 一起 干很多事情。一起干,不代表同時干,可能是 你干一個,他干一個,我們經(jīng)常在操作系統(tǒng)原理里邊講到, 并行 它是什么東西呢?感覺上大家在一起做,只是一種 感覺 。在面試的時候,很多時候是考驗你對一些概念上的東西是不是有一個深刻上的理解。當你有一個深刻理解的時候,你做的東西才不會那么走樣,否則的話,你只是記一個東西,很多時候,大家在面試的時候,都是在被那個 答案 。

         WebFlux 非常簡單,沒有以前那么復雜,從 Spring MVC 到 Spring WebFlux 是沒有難度的。

         ServletInpuStream.setReadListener or servletOutputStream.setWriterListener 當我們很了解,Spring MVC 的時候,不會很去了解 Servlet 的 API ,

        javax.servlet.http.HttpServletRequest

        • javax.servlet.ServletRequest#getInputStream

        在 3.1 的時候, Spring Boot 本身就是 Servlet 3.1 的支持,

        系統(tǒng)要求: Servlet Containers

        9.1 Servlet Containers

        Spring Boot supports the following embedded servlet containers:

        NameServlet Version
        Tomcat 9.04.0
        Jetty 9.43.1
        Undertow 2.04.0

        一個是 Read 一個是 Writer ,里邊有一個 事件監(jiān)聽 Listener ,

        javax.servlet.ServletInputStream#setReadListener

        javax.servlet.ReadListener
        1
        2
        3
        4
        5
        6
        7
        8
        public interface ReadListener extends EventListener {
        // 告訴你數(shù)據(jù)已經(jīng)準備好了,可以連接了
        void onDataAvailable() throws IOException;
        // 所有的數(shù)據(jù),我已經(jīng)讀完了
        void onAllDataRead() throws IOException;

        void onError(Throwable var1);
        }

        Readlistener 其實也是一個 事件回調(diào)

        所有的 NIO ,非阻塞,就是把一件事情分成了多件事情來做,比如說,NIO 會告訴你,InputStream 、 OutpusStream 有一個相應的事件 java.nio.file.WatchEvent.Kind 它是一個

        1
        2
        3
        4
        5
        6
        7
        /**
        * An event kind, for the purposes of identification.
        * 文本觀測的事件
        * @since 1.7
        * @see StandardWatchEventKinds
        */

        public static interface Kind<T> {

        NIO 里邊有,所謂的 連接事件、寫事件、讀事件,然后,

        NIO 是一部分一部分的數(shù)據(jù)把它傳遞過來,NIO 在數(shù)據(jù)量小的時候,或者說數(shù)據(jù)量不頻繁的時候,是沒有什么優(yōu)勢的。他對持續(xù)的鏈接,在 大并發(fā) 的情況下,它才會有一定的價值,很大程度上面,像 Netty 它就有很多的事件回調(diào),無論它異步還是同步,它是 NIO 的。

        他和 很多時候都很像, Netty 做的比較好,是因為它屏蔽了一些細節(jié),通過回調(diào)接口的方式讓你來進行相應的操作,然后你就會對它的操作變得簡單一點。Servlet 3.0 提供了異步,Servlet 3.1 提供了 NIO ,Servlet 3.1 提供了一種新型的方式叫做 WebSocket 的方式,

        Upgrade Processing

        (Servlet 3.1 規(guī)范里邊的)

        所謂的協(xié)議的升級,就是 WebSocket 第一次請求的時候是一個普通的 HTTP 請求,這時候,服務端或告訴它,我要把你相應的 TCP 的協(xié)議進行一個升級,進行一個轉(zhuǎn)換一下,這是一個機制,在 Servlet 3.1 里邊其實也是有的。

        在我們的 Tomcat 里邊是一種方式實現(xiàn)兩種方法,通過一種方式,可以實現(xiàn) webSocket ,也可以實現(xiàn) 普通的一種實現(xiàn),

         javax.servlet.http.HttpUpgradeHandler

        1
        2
        3
        4
        5
        public interface HttpUpgradeHandler {
        void init(WebConnection var1);

        void destroy();
        }

        在 Tomcat 8 里邊有一個 HTTP/2 的一個處理的方式,HTTP/2 完完全全就變成長連接,WebSocket 是一個版長連接,第一步不是長鏈接,第二步才是長連接,WebConnection 是一種,

        WebSocket 并不是一個瀏覽器的技術(shù),比方說,你手機的客戶端也可能支持這個技術(shù),這是 Http 和 webSocket 的一個變種吧,瀏覽器是我們 Web 客戶端的一種實現(xiàn),但是并不是所得的實現(xiàn),你如果用 Postman 來做這個操作,也是可以的。

        Servlet 3.1 不用 Servlet 3.1 是不是就不可以用 WebFlux 了呢?

        WebFlux 默認的是用 Netty 來實現(xiàn)它的 WebServer。那就是利用一些 Netty 的一些 API 來做它的操作,我們傳統(tǒng)的 MVC 用的是一些 Servlet 的 API ,請求和相應,我們,

        其實 WebFlux 默認的情況下并不是 異步 的。

        The other part of the answer is functional programming. Much as the addition of annotations in Java 5 created opportunities (such as annotated REST controllers or unit tests), the addition of lambda expressions in Java 8 created opportunities for functional APIs in Java. This is a boon for non-blocking applications and continuation-style APIs (as popularized by CompletableFuture and ReactiveX) that allow declarative composition of asynchronous logic. At the programming-model level, Java 8 enabled Spring WebFlux to offer functional web endpoints alongside annotated controllers.

        函數(shù)式編程,Spring WebFlux 依賴的版本必須是 JAVA 8 ,意味著它的很多東西都是由 Lambda 表達式來做的,我必須要用 Lambda 來做相應的事情,Spring 5 也對 Kotlin 做了很多的支持,

        Spring 每次推它之外的技術(shù),推什么死什么,推 Gurave,osji 兩個都掛了,Kotlin 不一定走太遠,java 中的腳本語言多如牛毛,jPhython, grauve, nodejs,各種…….一個語言好不好,并不是由于誰來站臺,假如所有安卓手機都用 Kotlin 的話,他也不一定流行,JAVA 主要是它的靜態(tài)性,Java 8 已經(jīng)快不維護了,但是市面上 Lambda 用的非常少,都是喜歡 接口設(shè)計模式,很少有人談論 Lambda 設(shè)計模式,Java 8 的函數(shù)式編程的設(shè)計模式,彈性太大,有一個相應的變化特性,彈性大,花樣比較多。

        RxJava ,安卓,和 Spring Cloud hystrix 的流行中也用到了 RxJava ,

        不用 Reactive Java,一樣可以實現(xiàn),只是一種實現(xiàn)方式。

        新技術(shù)的使用是未來的一個經(jīng)驗。大家相互報臭腳,Ibatis 一開始不鳥 Spring ,后來 Spring Framework ,Spring boot ,都往上面貼了。

        有一些新技術(shù),原理性的東西,官方不會講的很清楚。你用了也沒什么問題,大家都得過且過了,就是得過且過了,Lambda 你了解本質(zhì)的時候,覺得它很簡單,當你不了解它的時候,你就會覺得它非常難,對一個新的東西不要有抵制。趕緊去用,就不會有什么問題了,

        Lambda 調(diào)試,寫出來,短小精干,一個表達式短小精悍,甚至把一個方法抽到一個類里邊去,這個時候考驗你的設(shè)計能力。應該反思你的一些設(shè)計是不是過于的復雜了。23 種設(shè)計模式,真正有用的不到一半,確實是,調(diào)試起來比較麻煩,尤其是 IDE 里邊調(diào)試還行,線上調(diào)試就非常非常的麻煩了, Java Debuger 、save point 的方式,Lambda 性能并沒有太多的一個作用。

        靜態(tài)工廠是最沒有價值的一個東西,靜態(tài)工廠,不是很符合面向?qū)ο蟮姆绞剑?/span>

        了解 Reactor 的 框架應該怎么寫,Mono,F(xiàn)lux 兩個對象,WebFlux 和 WebMVC 是不能共存的。不了解 Spring MVC 直接用 spring boot ,只能去開發(fā),很多時候,不知道它的原理是什么,比如說 CORS 跨域,它到底怎么做的呢?如果 Spring MVC 沒有會的話,Spring 一半的功能都廢掉了。Spring Boot 99% 就是 Web 應用。

        1.4. Annotated Controllers

        Same as in Spring MVC

        Spring WebFlux provides an annotation-based programming model, where @Controller and @RestController components use annotations to express request mappings, request input, handle exceptions, and more. Annotated controllers have flexible method signatures and do not have to extend base classes nor implement specific interfaces.

        The following listing shows a basic example:

        1
        2
        3
        4
        5
        6
        7
        8
        @RestController
        public class HelloController {

        @GetMapping("/hello")
        public String handle() {
        return "Hello WebFlux";
        }
        }

        In the preceding example, the method returns a String to be written to the response body.

        和 web MVC 一樣,

         MVC 不僅僅,手機里邊也會有 MVC,MVC 最早來自于桌面軟件。

        Spring 是非常 成功 的 重復發(fā)明輪子 ,它是一個 左派,吊打別人,然后引起別人的同情,

        JAX-RS:Octorber 3, 2007 這個時候, Spring MVC 2.5.0才有,是從,2007-11-12月份,

        RS 里邊寫稿子的時間更早,

        JAX-RS 規(guī)范中:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        @HttpMethod(GET)
        @ProduceMime("text/plain")
        public Stirng listHeadername(@HttpContext HttpHeader headers){
        StringBuilder buf = new Stringbuilder();
        for (String header: headers.getRequestHeaders().keySet()){
        buf.append(header);
        buf.append("\n");
        }
        return buf.toString();
        }

        請求參數(shù),Spring 就是抄的,Spring 包括 Spring Framework 都是抄襲的別人的,Spring 確實簡化了很多開發(fā)。不需要依賴某些容器就可以做某些事情,這個確實是它的可取之處,但是并不代表它,自己有很大的蒼翼,包括 Spring Boot 也不是它自己的,

        1
        2
        3
        4
        5
        6
        7
        <build>
        <!-- Spring Boot 自帶的打包插件 -->
        <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        </build>

        我們不用打包插件,我們用內(nèi)置的容器也可以實現(xiàn)打包,但是我們并不是說,這個 Spring Boot 是抄襲的別人,大家不是不要用,我們要從本質(zhì),從源頭把握一個方向,JDO (java data Object 規(guī)范)。

         三流的公司在賣產(chǎn)品,二流的公司做技術(shù),一流的公司在做規(guī)范。

        規(guī)范是一種形而上學的東西,沒有一個具體的實現(xiàn),它就告訴你怎么做,怎么做,是一個思想上的東西。既然它是要給思想界的東西,一定經(jīng)過了廣泛的討論,外國傳過來的。

         Optional 可以避免空,Guave 做出了貢獻,這個東西在Spring MVC 中也是支持的就是變成了一個 JSON 了。

        加了 Optional

        沒有加 Optional

        Mono 就是單一的意思,就是欺負中國人不懂英文,如果某一天中國人強大起來了,他們都會學習文言文了。

        Mono.just("")

        這就是 WebFlux 的使用方式,

        WebFlux 的啟動方式和 Spring MVC 有區(qū)別。

        它是 NettyWebServer 的容器來啟動的。這里沒有 Servlet 規(guī)范了, HttpServletRequest request 就沒有依賴了,意味著我們不再依賴 Servlet 容器也可以 Run 起來一個 Web 應用了。

         WebFlux 除了,我們傳統(tǒng)的容器,還有 Netty 這種容器供我們選擇,還有 Spring MVC 也可以兼容,參數(shù)額也可以以前一樣,Java 6 做了一個 WebServer ,Java 9 又去做 WebServer 了。這里就沒有傳統(tǒng)的 Session 了,

         reactor.core.publisher.Mono 就相當于我們的 Optional,也就是它也可以為空,

        大家通過 技術(shù)理解 session,不夠深入。

        不再需要 request.getParameter("message") 這種方法去取了。他用,一種統(tǒng)一的 Spring MVC 的 Annotation 模糊了你的 web 容器,不關(guān)心你是哪一種容器的實現(xiàn),Netty 也行, Tomcat 也行,

        表單也是一樣的。

        1
        2
        3
        4
        5
        <form action="" method="POST">
        <input name="id" value="1"/>
        <input name="name" value="darian"/>
        <input name="submid" value="提交"/>
        </form>

        你點擊提交表單的時候,會進行表單的提交。

        • Cookie session 不要做,session 是做用戶狀態(tài),Session 跟蹤機制,(Session Tracking Mechainisms)不是 Servlet 獨有的跟蹤機制,它是任何 HTTP 的一種,第一種是 Cookies,反倒一個東西放到 cookies 里邊, JESSIONID , JESSIONID 是請求頭的一部分,因為 cookie 是請求頭的一部分,setCookies 的,然后根據(jù) JESSIONID ,必須是 JESSIONID ,如果不統(tǒng)一,大家怎么去操作呢,還有一個問題是跨域,跨域怎么來操作呢?就是 Cookie 里的東西它認識不認識,

        • SSL Sessions 是 TTTPS 的范疇

        • URL Rewriting URL 的重寫,當我 cookie 被禁掉的時候,我在 URL 后邊加上一個 JESSIONID,localhost:8080/message=darian&JESSIONID=112516

        JESSIONID 是關(guān)注用戶是不是同一個,傳統(tǒng)的 Servlet 容器都是存在內(nèi)存里邊了,分布式的東西,存到緩存里邊,0809 年流行,memeryCache+Tomcat,現(xiàn)在流行 Redis,Spring 有一個 Spring session,有一個實現(xiàn)方法和 Redis 打通,和數(shù)據(jù)庫打通也沒關(guān)系的。memeryCahe ,定期清除,但是 Redis 就非常簡單了,設(shè)置一個過期時間,就是可以了。大家不要限定于某種技術(shù),JWT 就是小兒科,Token 就是一個令牌,就是一個 Session ,就是一個 JESSIONID,auth 也是一樣的。

        Optional 和 Mono 是一樣的,

        Why

        一摸一樣為什么要用它呢,WebFlux 所用的 jsonWebServer 在處理 JSON 方面 比 Tomcat 確實是好一些。官方有一個性能的對比,第二個從你并發(fā)編程的角度,所有的方式方法來操作。

        如果你依賴 Servlet 的 API 的話,就會確實是有成本,

        函數(shù)式的 EndPoint

        JDBC 5 就會用 reactive 的這種方式來做,reactive Data ,mongodb 也可以來做。

        ServerRequest

        ServerRequest provides access to the HTTP method, URI, headers, and query parameters, while access to the body is provided through the body methods.

        ServerRequest 可以轉(zhuǎn)化我們相應的數(shù)據(jù),我們可以把 Person 對象轉(zhuǎn)化為 json 對象,可以換一種進行表達,

        1
        2
        HandlerFunction<ServerResponse> helloWorld =
        request -> ServerResponse.ok().body(fromObject("Hello World"));

        返回對象給 xxx ,告訴別人怎么處理,一個方面是我要處理請求,響應內(nèi)容,另一個方面,我要給它一個映射,在我們聲明的表達方式是 @GetMapping("user/get") 來表達,函數(shù)式的方式怎么去表達呢?我們就要換一種方式進行一種操作。

        Spring Boot actuator 查看Beans

        路由包括,請求轉(zhuǎn)發(fā),和請求處理。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        @Bean
        public RouterFunction helloWorldFlux() {
        // 一個是 Request 的映射,匹配規(guī)則
        RequestPredicate requestPredicate = GET("/webflux");
        HandlerFunction handlerFunction = new HandlerFunction() {
        // 處理請求
        @Override
        public Mono handle(ServerRequest serverRequest) {
        return ok().body(Mono.just("hello, world"), String.class);
        }
        };
        return route(requestPredicate, handlerFunction);
        }
        1
        2
        3
        4
        5
        6
        7
        8
        @Bean
        public RouterFunction personRouterFunction() {
        return route(POST("/webflux/user"), serverRequest ->
        ok().body(
        serverRequest.bodyToMono(User.class)
        .map(User::toString),
        String.class));
        }

        ,就是這種寫法言簡意賅,有時候確實不好調(diào)試,寫法要簡短精悍。

        有時候,確實很裝逼。

        它是一種未來的趨勢,Spring 社區(qū)都在推這個東西,

        Optional 被 Mono 代替了,Collection 被 Flux 代替了,除了 Controller 的方式,WebFlux 提供了一種函數(shù)式編程的方式來進行操作。

         懂得多一點不覺得很牛逼,如果懂得很多的時候,就覺得你很牛逼了。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        @Bean
        public RouterFunction UserRouterFuction() {
        return route(POST("/flux/user/add"), serverRequest ->
        ok().body(serverRequest.bodyToMono(User.class)
        .map(user -> userRepository.saveUser(user))
        .map(ApiResponse::apiResponseOk),
        ApiResponse.class))
        .andRoute(GET("/flux/user/getall"), serverRequest ->
        ok().body(just(userRepository.findAll())
        .map(ApiResponse::apiResponseOk),
        ApiResponse.class))
        .andRoute(POST("/flux/user/update"), serverRequest ->
        ok().body(serverRequest.bodyToMono(User.class)
        .map(user -> userRepository.update(user))
        .map(user -> userRepository.getById(user.getId()))
        .map(ApiResponse::apiResponseOk),
        ApiResponse.class))
        .andRoute(GET("/flux/user/get"), serverRequest ->
        ok().body(just(serverRequest.queryParam("id").get())
        .map(s -> userRepository.getById(Long.valueOf(s)))
        .map(ApiResponse::apiResponseOk),
        ApiResponse.class));
        }
        Reactive 是利用的 reactor ,reactor 是 reactive_stream 的實現(xiàn)。是 Spring 工程里的一種實現(xiàn),
        1
        2
        3
        4
        5
        6
        7
        8
        9
        @Bean
        public RouterFunction personRouterFunction() {
        return route(POST("/webflux/user"), serverRequest ->
        ok().body(
        serverRequest.bodyToMono(User.class)
        .subscribeOn(Schedulers.parallel())
        .map(User::toString),
        String.class));
        }
        在 Reactive 中,它的異步不異步,并沒有用到 Schedulers 里邊。

        JSR 跳出來了某種固定的局限,但是必須依賴于 Servlet API ,mercyblitz 08年就考了,在國外同事經(jīng)常聊規(guī)范,和國內(nèi)同事總是聊框架。框架能夠幫助你快速實現(xiàn)你的需求,但是并沒有告訴你如何它背后的原理發(fā)生了什么事情(文化上面有代溝)。在選型上評價一個框架好不好,主要看它能做什么,不能做什么。通過 縱向、橫向 兩個方向去比較。

        學無止境,

         認知上存在偏差 。問題的關(guān)鍵在于大家學習學沒有學到家,不用 Spring,不用 zookeeper,不用 Servlet 能夠去搞才行。

        reactive 有三種方式,事件驅(qū)動的,各有優(yōu)缺點,

        https://darian1996.github.io/2018/12/07/Spring-5-新特性之WebFlux/

        喜歡,在看



        瀏覽 82
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            久久艹夜夜 | 爽 好紧 别夹 喷水无码 | 美女搞机91. | 榴莲视频| 国产婷婷久久 | 三级别视频小说在线观看 | 欧美黄在线 | 橹撸视频日日操时时操 | 欧洲高潮视频在线看 | 国产偷窥熟女高潮精品 |