Vertx入門學習(含代碼)

一、Vertx是什麼?

github: https://github.com/vert-x3
官網:http://vertx.io/

Vert.x誕生於2011年,當時叫node.x,不過後來因爲某些原因改名爲Vert.x,目前官網最新版本是4.4.0,官網上介紹Vert.x是一個用於在JVM上構建高效應用程序的工具包,是JVM上的Reative開發套件。說白了,Vert.x就是一堆的jar包,提供了一系列的編程API接口,通過這些API可以實現異步編程。
Vert.x目前是我見過功能最強大、對第三方庫依賴最少的Java框架,是一個異步無阻塞的網絡框架,其參照物是node.js,基本上node.js能幹的事情,Vert.x都能幹,它只依賴Netty4以及Jacskon,Vert.x利用Netty4的EventLoop來做單線程的事件循環,所以跑在Vert.x上的業務不能做CPU密集型的運算,這樣會導致整個線程被阻塞,另外如果你需要建立分佈式的Vert.x,則再依賴HazelCast這個分佈式框架即可,注意Vert.x3必須基於Java8。由於基於JVM,所以Vert.x可以用其他語言來實現你的業務。
異步編程怎麼理解呢?對於寫過ajax的人來說,不難理解,$.ajax方法並不會阻塞,而是直接向下執行,等到遠程服務器響應之後,纔會回調success方法,那麼這時候success方法纔會執行。ajax下面的代碼不會等到success方法執行完畢之後再執行,這就是所謂的異步。如下:

console.log("1");
$.ajax({
    "url" : "/hello",
    "type" : "post",
    "dataType" : "json",
    "success" : function(val) {
        console.log("2");
    }
});
console.log("3");

瀏覽器會先輸出1,在hello方法沒有相應之前不會輸出2,但是會先輸出3,等接口響應success之後會輸出2,這就是異步,異步編程是Vert.x的一大特性,也是Vert.x的核心,Vert.x可以開發Web應用,但Vert.x不僅僅是一個Web開發框架,他更像Spring,是一個技術棧(Vert.x生態可以查看https://github.com/vert-x3/vertx-awesome),或者說是一個Vert.x生態體系。在這個體系中,Vert.x只是提供了Web開發的能力。下面對Vertx和Spring做一個對比:

項目 Spring Vertx
核心框架 spring-core vertx-core
Web開發 spring-webmvc vertx-web
jdbc框架 spring-jdbc vertx-jdbc-client
redis spring-data-redis vertx-redis-client
微服務 spring-cloud vertx-hazelcast

可以說,很多spring能做的事情,Vertx也都能實現。那麼既然如此,Spring如此強大,社區如此活躍,爲何還會有Vertx呢?他們之前區別的核心點就只有一個:Spring的操作是同步的,Vertx的操作是異步的。異步帶來了更高的性能,但同時也帶來了編碼和調試的複雜度,但不得不說異步可能是未來的一個趨勢,至少在Java實現高性能服務器上的一個趨勢。
在Java領域,做Web開發我們一般有很多的選擇,比如使用原生的Servlet,比如使用SpringMVC,再比如使用Struts等等總之你有很多的選擇。在國內,目前來講,SpringMVC作爲Spring體系下的Web層架構,是深受企業青睞的,絕大部分的企業可能都在使用SpringMVC,而對於我們今天要說的Vert.x這個Web層框架,卻很少有人知道,但它卻是僅次於SpringMVC,排名第二的一個Web層框架。
Vert.x是基於事件的,提供一個事件驅動編程模型,使用Vert.x作爲服務器時,程序員只要編寫事件處理器event handler即可,當TCP socket有數據時,event handler理解被創建調用,另外它還可以在以下幾種情況激活: ‘當事件總線Event Bus接受到消息時,’ ‘當接收到HTTP消息時,’ 當一個連接斷開時’,’ ‘當計時器超時時.’
作爲服務層處理邏輯這一層基本上對應的傳統Java裏的領域模型處理層,各種Service調用以及對數據層的調用,差不多是一個承上啓下的一層,傳統的模型裏,這一層基本上都是同步調用,即使有異步調用,也是與業務邏輯分離的異步,如果全異步會導致業務邏輯碎亂,代碼很難描述清楚,到這裏你會發現Vert.x其實不太好融合到業務性很強的服務層裏,其主要原因如下
1、自身是異步體系,不適合描述順序邏輯性強的業務。
2、由於異步的問題,訪問數據層也必須是異步,導致業務模型進一步碎片化。

二、Vertx基本概念

我們學習一個新東西,都要去了解理解它的基本概念,學習Vert.x也是如此。那麼Vert.x又有哪些基本概念呢?

  • Verticle:Vert.x的執行單元,即程序的入口,它可以用JS、Ruby、Java等多語言來編寫,每個語言可能實現的方式不一樣,比如Java需要繼承一個AbstractVerticle抽象類。在同一個Vert.x實例中可以同時執行多個Verticle,一個應用可能由多個Verticle組成,它們被部署到不同的網絡節點上,彼此之間通過在Vert.x的事件總線(event bus)上交換信息來通信。
  • Module:Vert.x應用由一個或者多個modules來實現,一個module由多個verticles來實現,所以可以把module理解爲Java package,裏面可能是特定業務的實現或者公共的服務實現(那些可以重用的服務),Vert.x編寫好的module可以發佈到maven的倉庫裏,以zip包裝成二進制格式,或者發佈到vert.x module 註冊中心,實際上這種以模塊方式的開發,支撐着整個Vert.x生態系統。
  • Event Loops:事件循環,是由Vert.x啓動的事件處理線程,也是Vert.x項目對外開放的入口,Vert.x由此接收請求事件,一個Vert.x由一個或者多個事件循環線程組成,線程最大數爲主機有效的CPU核數。處理函數是handler接口,用來處理事件。
  • Event Loop verticle:事件的業務處理線程,存在於Event Loop中,用於處理非阻塞短任務。
  • Event bus:是Vert.x的核心,在集羣中容器之間的通信,各個Verticle之間的通信也都是經過Event bus來實現的,所以Event bus存在堵塞的可能。
  • Shared Data(共享數據):消息通過bus可以在各個Vert.x實例直接傳輸,但是如果多個Verticle在一個Vert.x實例內,是可以避免進行消息傳輸的,比如單個JVM內,你不會通過兩個socket互相在兩個Java對象之間傳輸消息的,這是同樣的道理,但是因爲實例隔離,因爲actor模型,所以對象數據如果要傳輸到handler裏必須通過消息傳輸。Shared Data是Vert.x提供的一個簡單共享map和set,用來解決各個Verticle之間的數據共享的,數據被存儲到一個不可變的數據結構裏,各個實例可以直接通過此API獲取數據。
  • Worker Verticle(阻塞處理):事件處理之外肯定會發生長時間數據處理請求,比如處理一個圖片上傳,然後轉存到磁盤等,此時就需要事件的業務處理線程用來處理長時間阻塞任務,worker verticle就是這個阻塞處理線程,是一種阻塞式的方法,但是無法做到併發水平擴展,在Verticle類型中有一種特別的verticle叫做worker,與標準的verticle不同的是它採用的是vert.x內部的另外一種線程池叫做worker pool,而不是使用event loop ,worker verticle不會並行的執行handler,而是阻塞式的,等前一個handler處理完了纔會執行後面的請求,這種的適合CPU密集型的,標準的verticle適合IO密集型的。vert.x爲了支持標準的和阻塞的worker verticle提供了一種混合線程模型,你可以根據自己的需求按需選擇合適的線程模型。
    純文字的,可能沒什麼概念,下面我們來看一下Vertx的框架圖,加深印象,便於理解:
    在這裏插入圖片描述

三、Vertx能幹什麼?

一句話總結:Java能做的,Vert.x都能做。咱這裏主要列出來Vert.x擅長做什麼?

  • Web開發,Vert.x封裝了Web開發常用的組件,支持路由、Session管理、模板等,可以非常方便的進行Web開發。不需要容器!不需要容器!不需要容器!
  • TCP/UDP開發,Vert.x底層基於Netty,提供了豐富的IO類庫,支持多種網絡應用開發。不需要處理底層細節(如拆包和粘包),注重業務代碼編寫。
  • 提供對WebSocket的支持,可以做網絡聊天室,動態推送等。
  • Event Bus(事件總線)是Vert.x的神經系統,通過Event Bus可以實現分佈式消息,遠程方法調用等等。正是因爲Event Bus的存在,Vert.x可以非常便捷的開發微服務應用。
  • 支持主流的數據和消息的訪問redis mongodb rabbitmq kafka 等。
  • 分佈式鎖,分佈式計數器,分佈式map的支持。

四、Vertx的技術體系

上面也提到了,Vert.x和Spring一樣,也有着完善的生態,具體可以查看https://github.com/vert-x3/vertx-awesome 我們可以看到,每一塊內容都提供了多種的實現,有官方支持的版本還有社區版本。下面我們具體介紹下技術體系中官方支持的版本。

  • 核心模塊。Vert.x核心模塊包含一些基礎的功能,如HTTP,TCP,文件系統訪問,EventBus、WebSocket、延時與重複執行、緩存等其他基礎的功能,你可以在你自己的應用程序中直接使用。可以通過vertx-core模塊引用即可。
  • web模塊。Vert.x Web是一個工具集,雖然核心模塊提供了HTTP的支持,但是要開發複雜的Web應用,還需要路由、Session、請求數據讀取、Rest支持等等還需要Web模塊,這裏提供了上述的這些功能的API,便於開發,除了對Web服務的開發以外,還提供了對Web客戶端請求的支持,通過vertx-web-client即可方便的訪問HTTP服務。有朋友可能會有疑惑,我明明可以使用JDK提供的URL來請求HTTP服務啊,使用Vert.x一定要注意,Vert.x是一個異步框架,請求HTTP服務是一個耗時操作,所有的耗時,都會阻塞Event Bus,導致整體性能被拖垮,因此,對於請求Web服務,一定要使用Vert.x提供的vertx-web-client模塊。
  • 數據訪問模塊:Vert.x提供了對關係型數據庫、NoSQL、消息中間件的支持,傳統的客戶端因爲是阻塞的,會嚴重影響系統的性能,因此Vert.x提供了對以上客戶端的異步支持。具體支持的數據訪問如下:MongoDB client,JDBC client,SQL common,Redis client,MySQL/PostgreSQLclient。
  • Reactive響應式編程:複雜的異步操作會導致異步回調地獄的產生,看下面的代碼,這是我在Vert.x提供的例子中找到的,我們不去管這段代碼幹了啥,只是看後面的}就很驚訝了,如果操作更爲複雜一些,會嵌套的層次更多,通過reactive可以最小化的簡化異步回調地獄。
// create a test table
execute(conn.result(), "create table test(id int primary key, name varchar(255))", create -> {
  // start a transaction
  startTx(conn.result(), beginTrans -> {
    // insert some test data
    execute(conn.result(), "insert into test values(1, 'Hello')", insert -> {
      // commit data
      rollbackTx(conn.result(), rollbackTrans -> {
        // query some data
        query(conn.result(), "select count(*) from test", rs -> {
          for (JsonArray line : rs.getResults()) {
            System.out.println(line.encode());
          }
 
          // and close the connection
          conn.result().close(done -> {
            if (done.failed()) {
              throw new RuntimeException(done.cause());
            }
          });
        });
      });
    });
  });
});

再看一個使用Reactive2構建的多步操作的代碼,paramCheckStep,insertPayDtlStep,requestStep等等都是異步方法,但這裏就很好的處理了異步回調的問題,不再有那麼多層的大括號,代碼結構也geng

public void scanPay(JsonObject data, Handler<AsyncResult<JsonObject>> resultHandler) {
    paramCheckStep(data) // 參數校驗
            .flatMap(this::insertPayDtlStep) // 插入流水
            .flatMap(x -> requestStep(x, config)) // 請求上游
            .flatMap(this::cleanStep) //參數清理
            .subscribe(ok -> {
                        logger.info("成功結束");
                        resultHandler.handle(Future.succeededFuture(ok));
                    },
                    err -> {
                        logger.error("正在結束", err);
                        resultHandler.handle(Future.failedFuture(err));
                    }
 
            );
}
  • 整合其他模塊
    • 郵件客戶端。Vert.x提供了一簡單STMP郵件客戶端,所以你可以在應用程序中發送電子郵件。
    • STOMP客戶端與服務端。Vert.x提供了STOMP協議的實現包括客戶端與服務端。
    • Consul Client。consul是google開源的一個使用go語言開發的服務發現、配置管理中心服務。內置了服務註冊與發現框 架、分佈一致性協議實現、健康檢查、Key/Value存儲、多數據中心方案。
    • RabbitMQ Client Kafka Client。消息隊裏的客戶端支持。
    • JCA適配器。Vert.x提供了Java連接器架構適配器,這允許同任意JavaEE應用服務器進行互操作。
  • 認證與授權:Vert.x提供了簡單API用於在應用中提供認證和授權。
    • Auth common 通用的認證API,可以通過重寫AuthProvider類來實現自己的認證。
    • JDBC auth 後臺爲JDBC的認證實現。
    • JWT auth 用JSON Web tokens認證實現。
    • Shiro auth 使用Apache Shiro認證實現。
    • MongoDB auth MongoDB認證實現。
    • OAuth 2 Oauth2協義認證實現。
    • htdigest auth 這個是新增一種認證的支持
  • 微服務:Vert.x提供多個組件構建基於微服務的應用程序。比如服務發現(Vert.x Service Discovery)、斷路器(Vert.x Circuit Breaker)、配置中心(Vert.x Config)等。

五、快速體驗:搭建一個簡單的Vertx項目並輸出Hello World

首先新建一個Maven項目,然後在pom.xml中加入相關的依賴和插件,如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>vertxone</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <vertx.version>4.0.0</vertx.version>
        <main.class>org.example.Main</main.class>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>${vertx.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Main-Class>${main.class}</Main-Class>
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                            <artifactSet/>
                            <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-prod.jar</outputFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

跟其它Maven項目一樣,我們首先定義了項目的GroupId,ArtifactId以及版本號,隨後我們定義了兩個屬性,分別是:vertx.version,也就是Vert.x的版本號,此處我們使用最新的Vert.x版本,也就是4.4.0;以及main.class,也就是我們要使用的包含有main函數的主類。之後我們引入了兩個Maven插件,分別是maven-compiler-plugin和maven-shade-plugin,前者用來將.java的源文件編譯成.class的字節碼文件,後者可將編譯後的.class字節碼文件打包成可執行的jar文件,俗稱fat-jar。
然後我們在src/main/java/org/example目錄下新建兩個java文件,分別是Main.java和MyFirstVerticle.java,代碼如下:

Main.java

package org.example;

import io.vertx.core.Vertx;

/**
 * @author dxm
 * @description
 * @ClassName
 * @date 2023-03-14 15:19
 */
public class Main {
    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(MyFirstVerticle.class.getName());
    }
}

MyFirstVerticle.java

package org.example;

import io.vertx.core.AbstractVerticle;

/**
 * @author dxm
 * @description
 * @ClassName
 * @date 2023-03-14 15:25
 */
public class MyFirstVerticle extends AbstractVerticle {

    public void start() {
        vertx.createHttpServer().requestHandler(req -> {
            req.response()
                    .putHeader("content-type", "text/plain")
                    .end("Hello World222!");
        }).listen(8080);
    }
}

然後用Maven的mvn package命令打包,隨後在src的同級目錄下會出現target目錄,進入之後,會出現vertxone-1.0-SNAPSHOT.jar和vertxone-1.0-SNAPSHOT-prod.jar兩個jar文件,後者是可執行文件,在有圖形界面的操作系統中,您可雙擊執行或者用以下命令:java -jar vertxone-1.0-SNAPSHOT-prod.jar執行,然後打開瀏覽器,在瀏覽器的地址欄中輸入:http://localhost:8080/ 便可看到熟悉的Hello World!啦。
在這裏插入圖片描述
我們也可以使用Launcher來替代Main類,這也是官方推薦的方式,在pom.xml中加入main.verticle屬性,並將該屬性值設置爲maven-shade-plugin插件的manifestEntries的Main-Verticle對應的值,最後修改main.class爲io.vertx.core.Launcher,修改後的pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>vertxone</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <vertx.version>4.0.0</vertx.version>
        <main.class>io.vertx.core.Launcher</main.class>
        <main.verticle>org.example.MainVerticle</main.verticle>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>${vertx.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Main-Class>${main.class}</Main-Class>
                                        <Main-Verticle>${main.verticle}</Main-Verticle>
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                            <artifactSet/>
                            <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-prod.jar</outputFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

然後在src/main/java/org/example目錄下新增MainVerticle.java文件,代碼如下:

package org.example;

import io.vertx.core.AbstractVerticle;

/**
 * @author dxm
 * @description
 * @ClassName
 * @date 2023-03-14 3:48 PM
 */
public class MainVerticle extends AbstractVerticle {

    public void start() throws Exception {
       vertx.deployVerticle(MyFirstVerticle.class.getName());
    }
}

然後重新打包後執行,便可再次看到Hello World!。

六、單元測試

下面我們將會介紹測試部分,首先引入兩個新的測試依賴,修改後的pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>vertxone</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <vertx.version>4.0.0</vertx.version>
        <main.class>io.vertx.core.Launcher</main.class>
        <main.verticle>org.example.MainVerticle</main.verticle>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>${vertx.version}</version>
        </dependency>

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-unit</artifactId>
            <version>${vertx.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Main-Class>${main.class}</Main-Class>
                                        <Main-Verticle>${main.verticle}</Main-Verticle>
                                    </manifestEntries>
                                </transformer>

                                <!--多語言支持在打包時需加入以下轉換器-->
                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>META-INF/services/io.vertx.core.spi.VerticleFactory</resource>
                                </transformer>
                                
                            </transformers>
                            <artifactSet/>
                            <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-prod.jar</outputFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

隨後在src/test/java/org/example目錄下新增MyFirstVerticleTest.java文件:

package org.example;
import io.vertx.core.Vertx;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * @author dxm
 * @description
 * @ClassName
 * @date 2023-03-14 3:56 PM
 */
@RunWith(VertxUnitRunner.class)
public class MyFirstVerticleTest {
    private Vertx vertx;

    @Before
    public void setUp(TestContext context){
        vertx = Vertx.vertx();
        vertx.deployVerticle(MyFirstVerticle.class.getName(), context.asyncAssertSuccess());
    }

    @After
    public void tearDown(TestContext context) {
        vertx.close(context.asyncAssertSuccess());
    }

    @Test
    public void testApplication(TestContext context) {
        final Async async = context.async();

        vertx.createHttpClient().getNow(8080, "localhost", "/", response -> {
            response.handler(body -> {
                context.assertTrue(body.toString().contains("Hello"));
                async.complete();
            });
        });
    }
}

執行該測試案例便可得到期望的結果,有興趣的可以練習一下。

總結

最後呢,我想說咱程序員不能只會一種語言,開發框架也不能只知道Spring,也得去了解學習接觸一些其他的框架,拓展自己的知識面,在後面解決問題的時候,你就會發現,書到用時方恨少,所以還是要在日常進行不斷的積累和總結,然後在適當的場景下選擇合適的技術選型來解決問題,適合自己的纔是最好的,最後給大家佈置一個作業,就是結合自己現在的項目結構分層寫一下增刪改查的接口,感興趣的你,趕緊去試試吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章