说起java的异常处理,大家首先想到的是简单粗暴的try.....catch...finally.
但在Vert.x中,Vert.x为我们封装了更加优雅的异常处理方式,大多数情况下不需要我们手写try....catch。
Vert.x中,大多数Handler接口都是Handler<AsyncResult<T>>的形式,其中AsyncResult,里面既封装了正确的返回结果,也封装了Vert.x帮我们捕捉到的异常。
1、我们修改配置文件数据库密码,将它改为错误的密码,用来测试异常。
{
"port": 3306,
"host": "127.0.0.1",
"database": "db",
"user": "root",
"password": "errorPassword"
}2、编写HandleExceptionVerticle代码
package vertx;
import io.vertx.config.ConfigRetriever;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.mysqlclient.MySQLConnectOptions;
import io.vertx.mysqlclient.MySQLPool;
import io.vertx.sqlclient.*;
import java.util.ArrayList;
public class HandleExceptionVerticle extends AbstractVerticle {
//声明Router
Router router;
//配置连接参数
MySQLConnectOptions connectOptions;
//配置连接池 Pool options
PoolOptions poolOptions = new PoolOptions()
.setMaxSize(5);
//Create the client pool
MySQLPool client;
@Override
public void start(Promise<Void> startPromise) throws Exception {
ConfigRetriever retriever = ConfigRetriever.create(vertx);
retriever.getConfig(ar -> {
if (ar.failed()) {
// Failed to retrieve the configuration
} else {
JsonObject config = ar.result();
connectOptions = new MySQLConnectOptions()
.setPort(config.getInteger("port"))
.setHost(config.getString("host"))
.setDatabase(config.getString("database"))
.setUser(config.getString("user"))
.setPassword(config.getString("password"));
client = MySQLPool.pool(vertx, connectOptions, poolOptions);
//初始化Router
router = Router.router(vertx);
//配置Router解析url
router.route("/").handler(
req -> {
req.response()
.putHeader("content-type", "text/plain")
.end("Hello from Vert.x!");
}
);
//配置Router解析url
router.route("/test/list").handler(
req -> {
var page = (Integer.valueOf(req.request().getParam("page")) - 1) * 10;
var size = Integer.valueOf(req.request().getParam("size"));
//Get a connection from the pool
this.getCon()
.compose(con -> this.getRows(con, page, size))
.onSuccess(row -> {
var list = new ArrayList<JsonObject>();
row.forEach(item -> {
var json = new JsonObject();
json.put("id", item.getValue("id"));
json.put("name", item.getValue("name"));
json.put("age", item.getValue("age"));
json.put("info", item.getValue("info"));
list.add(json);
});
req.response()
.putHeader("content-type", "application/json")
.end(list.toString());
})
.onFailure(throwable -> {
//真实的项目开发中,我们可以在这里捕获Future+Promise异步链式调用的异常
//在这里统一处理,比如写入日志文件
req.response()
.putHeader("content-type", "application/json")
.end(throwable.toString());
});
}
);
//将Router与vertx HttpServer 绑定
vertx.createHttpServer().requestHandler(router).listen(8888, http -> {
if (http.succeeded()) {
startPromise.complete();
System.out.println("HTTP server started on port 8888");
} else {
startPromise.fail(http.cause());
}
});
}
});
}
//第一步 获取数据库链接
private Future<SqlConnection> getCon(){
Promise<SqlConnection> promise = Promise.promise();
client.getConnection(ar1 -> {
if (ar1.succeeded()) {
System.out.println("Connected");
//Obtain our connection
SqlConnection conn = ar1.result();
promise.complete(conn);
} else {
System.out.println("数据库连接不成功!");
//Vert.x帮我们捕获异常后,我们只需要做接下来的处理即可,比如写日志
promise.fail(ar1.cause()); //这里就相当于继续向上抛出异常,用Promise来向上抛异常
}
});
return promise.future();
}
//第二步 用获取到的链接查询数据库
private Future<RowSet<Row>> getRows(SqlConnection conn, Integer page, Integer size){
Promise<RowSet<Row>> promise = Promise.promise();
conn
.preparedQuery("select id, name, age, info from person limit ?, ?")
.execute(Tuple.of(page, size), ar2 -> {
//Release the connection to the pool
conn.close();
if(ar2.succeeded()){
promise.complete(ar2.result());
}else{
promise.fail(ar2.cause());
}
});
return promise.future();
}
}3、启动测试
控制台

接口返回
