Vert.x 导论之一:第一个Vert.x 3 应用

你听有些人说Vert.x很酷炫,你可能想亲自尝试下。于是你很自然的想到“我该从哪里起步?”那么这个帖子就是为你准备的。包含了如何构建一个很简单的vert.x应用,如何测试,打包并执行。总之,在你开发自己的开创性应用前所需要知道的一切。

这个帖子中的代码可以在github(https://github.com/cescoffier/my-vertx-first-app)上找到,本文同时也是Vertx 导论系列的一部分。这部分代码在post-1分支中。

让我们开工吧

首先,我们使用Apache Maven来创建项目,但你也可以使用Gradle或者你喜欢的其他构建工具。你可以使用Maven自带的jar模板原型来创建项目结构,不过事实上,你只需要有如下目录结构的一个目录:
1.一个 src/main/java目录
2.一个 src/test/java目录
3.一个pom.xml文件
所以,你的项目将会是如下结构:

.
├── pom.xml
├── src
│   ├── main
│   │   └── java
│   └── test
│       └── java

我们创建如下内容的pom.xml文件。

<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>io.vertx.blog</groupId>
  <artifactId>my-first-app</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-core</artifactId>
      <version>3.5.1</version>
    </dependency>
  </dependencies>

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

</project>

pom.xml文件的内容非常明确:

  • 声明了 vertx-core的依赖
  • 配置maven-compiler-plugin使用java8
    第二条很重要,Vert.x 应用需要Java 8。

让我们编码吧

我们准备好了pom.xml文件。现在开始编码工作。。。创建src/main/java/io/vertx/blog/first/MyFirstVerticle文件,内容如下:

package io.vertx.blog.first;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;

public class MyFirstVerticle extends AbstractVerticle {

  @Override
  public void start(Future<Void> fut) {
    vertx
        .createHttpServer()
        .requestHandler(r -> {
          r.response().end("<h1>Hello from my first " +
              "Vert.x 3 application</h1>");
        })
        .listen(8080, result -> {
          if (result.succeeded()) {
            fut.complete();
          } else {
            fut.fail(result.cause());
          }
        });
  }
}

这只是个很普通的应用。该类继承了AbstractVerticle。在Vert.x的世界里,一个verticle是一个组件。通过继承AbstractVerticle,该类可以访问并使用vertx字段。

当verticle被部署后start方法被调用。我们还能实现一个stop方法,在本例中Vert.x为我们做了默认的垃圾回收。start方法会接收到一个Future对象,Future对象可以用来通知Vert.x我们的开始序列已经执行完毕或者执行报错。Vert.x具有异步/非阻塞的特性。verticle被部署时不会一直等待到start方法被执行完成。所以,Future参数对通告start方法执行完毕而言很重要。

start方法创建了一个HTTP服务器还在其基础上添加了一个请求处理器。该请求处理器是一个lambda表达式,被放入requestHandler方法,每当HTTP服务器接收到一个请求时都会被调用。我们这里只是回复Hello。最后,该服务器被绑定在8080端口。由于这可能失败(因为这个端口可能早已被占用),我们传入另一个lambda表达式来检查该连接是否成功。如上所述,如果成功就调用fut.complete否则调用fut.fail来报告失败。

使用如下命令来编译应用:

mvn clean compile

顺利的话,应该能正常执行。

让我们添加测试单元吧

能开发一个应用很好,但是再小心也不为过,所以我们要添加测试。这个测试使用JUnit和vertx-unit -一个随vert.x发布的框架,目的在于让vert.x应用的测试更加方便。

打开pom.xml文件,添加如下两个依赖:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-unit</artifactId>
  <version>3.5.1</version>
  <scope>test</scope>

现在创建src/test/java/io/vertx/blog/first/MyFirstVerticleTest.java文件,内容如下:

package io.vertx.blog.first;

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;

@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 testMyApplication(TestContext context) {
    final Async async = context.async();

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

以上是对verticle的JUnit测试。该测试使用vertx-unit,所以我们使用一个定制的runner。vertx-unit 方便了异步交互的测试,而异步交互就是vert.x应用的基础。

setUp方法中,我们创建了一个Vertx的实例并部署了我们的verticle。你可能注意到不同与传统的JUnit @Before方法,我们的Before方法接收一个TestContext。该对象辅助我们进行异步测试。比方说,当我们部署verticle时,verticle异步启动,在verticle正常启动前我们不能做任何检测。所以,在 deployVerticle方法的第二个参数位置,我们传入一个结果处理器:context.asyncAssertSuccess()。如果verticle没有正常启动,这个方法会失败。此外,这个方法会一直等到verticle完成了启动序列。记住,在verticle中,我们调用fut.complete()。所以context.asyncAssertSuccess()方法会一直等待直到fut.complete()被调用,并且如果中途出现异常,就让测试失败。

tearDown方法就很直观,就是结束我们创建的vertx实例。

现在来看我们应用的测试:testMyApplication方法。该测试向应用发出请求并检测结果。由于发出请求和接收响应都是异步的,我们需要有一种方式来控制这一点。和setUptearDown方法一样,test方法接收一个TestContext对象。我们从这个对象中创建一个异步处理器(async),当测试完成时使用async.complete()通知测试框架测试完成。

一旦async处理器被创建好,我们创建一个HTTP客户端并用getNow()方法向我们的应用发出一个HTTP请求(getNow是get(...).end()的缩写)。响应由一个lambda表达式处理。在这个lambda表达式中我们通过给处理器方法传入另一个lambda表达式来获取响应体。body参数就是响应体(是buffer对象)。我们检测确认响应体中含有"Hello"字符串并声明测试结束。

我们再说下断言,不像传统的JUnit测试,这里使用context.assert...事实上,如果断言失败,该方法会马上终止测试。由于Vert.x应用的异步特性总是使用这些断言方法很重要。

我们的测试可以用IDE或者Maven发起:

mvn clean test

打包

我们来总结一下,目前为止,我们有一个应用和一个测试,现在我们来打包应用。在这个贴子里,我们把这个应用打包成fat jar。一个fat jar 是一个独立可执行jar文件,含有运行应用所需要的所有依赖。由于只有一个文件,这种方式打包Vert.x应用很方便,也利于执行。

为了创建一个fat jar,编辑pom.xml文件在</plugins>前添加如下代码片段:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>2.4.3</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>io.vertx.core.Starter</Main-Class>
              <Main-Verticle>io.vertx.blog.first.MyFirstVerticle</Main-Verticle>
            </manifestEntries>
          </transformer>
        </transformers>
        <artifactSet/>
        <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar</outputFile>
      </configuration>
    </execution>
  </executions>
</plugin>

上面使用maven-shade-plugin 来创建fat jar. 在manifestEntries 中指定了verticle的名字。你可能琢磨Starter类从何而来,事实上这个类来自vert.x。该类将会创建vertx实例并部署verticle。

配置好这个插件后,我们执行如下命令:

mvn clean package

该命令将创建 target/my-first-vertx-app-0.0.1-SNAPSHOT-fat.jar 文件,该文件包含我们的应用以及所有相关依赖(包括vert.x本身)。

执行我们的应用吧

有一个fat jar很好,但我们更想看应用运行效果,如之前所述,归功于fat jar打包方式,运行Vert.x应用很简单:

java -jar target/my-first-vertx-app-0.0.1-SNAPSHOT-fat.jar

然后,打开浏览器,访问http://localhost:8080

想要停止应用,敲击CTRL+C

结论

这门Vert.x 3速成课展示了如何使用Vert.x 3来开发一个简单应用,测试打包并运行。你现在掌握了用Vert.x 3构建神奇系统的基础。下一次内容是配置我们的应用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容