你听有些人说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
方法。该测试向应用发出请求并检测结果。由于发出请求和接收响应都是异步的,我们需要有一种方式来控制这一点。和setUp
和tearDown
方法一样,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构建神奇系统的基础。下一次内容是配置我们的应用。