说起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、启动测试
控制台
接口返回