vert.x本身也有一些bug,用的过程当中发现了,一定会去找到根本原因,能修复的就直接修复了,修复不了的就想办法跳过。
我这边用的是3.5.2。版本有点旧了,至于新的有没有修复,我也就不去探究了,简单记录一下。
注意:修复框架的代码,一定要做好注释和笔记,以应对升级框架版本的情况。
HTTP请求方法不正确的时候状态码是404,应该是405
发布一个接口,定义的是get,你却用post调用,vertx返回的是404,准确一些应该是405。我直接说怎么修复的吧。
第一个类:io.vertx.ext.web.impl.RouteImpl
具体的方法是:
synchronized boolean matches(RoutingContextImplBase context, String mountPoint, boolean failure)。
大约在230行。
这个方法是用来判断当前请求是否匹配你定义发布的接口,非常关键的方法。
有下面一行代码:
if (!methods.isEmpty() && !methods.contains(request.method())) {
return false;
}
我发布了一个路由,而且定义了一些方法,但是你请求的方法并不在里面,直接返回false。外层在处理的时候,它就会认为没有找到,因此我们要做一件事情:要能够准确捕获到405的情况,并且在外层可以捕获到,把405的信息返回调用方。
那怎么才能算405呢?常见的就是路径匹配上了,但方法不对,就是了。
但在vertx里面会稍微复杂一下,我修复的方式,也不一定是完全正确的,但能够满足我的需求。
我的处理逻辑如下:
- 定义了路径,并且路径匹配上了(有的路由可以不定义路径,仅做预处理)。
- 定义了方法,方法没有匹配上。
- 没有定义模糊匹配。
这3点目前是没有问题的,第一点也处理了子路由的情况。注意:但是可能还不够,因为它在后面又判断了一系列参数,反正我没有用到。
具体代码如下:
if (path != null && pattern == null && !pathMatches(mountPoint, context)) {
return false;
}
if (!methods.isEmpty() && !methods.contains(request.method())) {
/**
* update begin
*/
if (path!=null&&pattern==null){
//这种情况下就是,Url匹配上了,但是方法不正确,返回一个方法不允许的错误。
String method=methods.toArray(new HttpMethod[0])[0].name();
throw new MethodNotAllowedException(method);
}
/**
* update end
*/
return false;
}
我调整了一下顺序,先判断路径,再判断方法;人家的是反着的。但是按照他们的顺序,你要判断405的话,判断完方法还得判断路径,所以我调整了一下。
然后自定义了一个异常,同时把应该采用的方法也放进去了(直接取了第一个),这个异常是为了让外层捕获和处理。
第二个类:io.vertx.ext.web.impl.RoutingContextImplBase
具体方法
protected boolean iterateNext() {}
在最后面有一个catch
catch (IllegalArgumentException e) {
if (log.isTraceEnabled()) log.trace("IllegalArgumentException thrown during iteration", e);
// Failure in handling failure!
unhandledFailure(400, e, route.router());
return true;
}
这里会捕捉到刚才的异常,判断一下,直接返回错误消息,return true就行了。
catch (Exception e) {
/**
* update start
*/
if (e instanceof MethodNotAllowedException){
this.response().setStatusCode(HttpResponseStatus.METHOD_NOT_ALLOWED.code());
this.response().end("方法不允许,你应该用这个方法来调用:"+e.getMessage());
return true;
}
/**
* update end
*/
if (log.isTraceEnabled()) log.trace("IllegalArgumentException thrown during iteration", e);
// Failure in handling failure!
unhandledFailure(400, e, route.router());
return true;
}
总体来说还是比较简单的。
使用MySQLClient.createShared(Vertx vertx, JsonObject config)创建的mysql客户端在查询字段类型为:bit(1)的时候会出错。
跟代码的过程就不详细说了,直接说结论。
我们都知道对于mysql来讲,bit(1)可以用作布尔变量,而且驱动返回的就是Boolean,但是当大于1的时候,就会返回byte[]。
上面的方法返回的客户端是AsyncSQLClientImpl,这个客户端返回的连接对象是:
io.vertx.ext.asyncsql.impl.MySQLConnectionImpl
当然它内部有个真正的引用,是:
com.github.mauricio.async.db.mysql.MySQLConnection
罪魁祸首就是它,当它查询bit(1)的时候,返回的居然是个byte[],根本不符合人家mysql的规范。
然后vertx的Json在增加内容的时候,处理byte[]的时候,会使用BASE64做处理,本来是0和1,然后看的时候就变成了AQ==,也是非常郁闷。
当然这并不是它不能处理byte[],只不过是内存里面是这样存储byte的。
那么能不能用getBinary方法取呢,可以。这个返回byte[]数组,但是取出来你可能还得取出第一位去判断是1还是0。但没有必要,它本身就是错的。
而且仅仅用来判断状态还是可以的,但是如果传输的话,万万是不行的。
解决思路:以后别用这个了,还是用JDBC吧,已经用了,就换了,改动不大,如下:
JDBCClient.createShared(Vertx vertx, JsonObject config)
这个是没有问题的。
当然也引出了其它问题,比如用vert.x的json传输byte[]的时候,要注意一下,特别是和异构系统的数据传输交互问题。
来源:CSDN
作者:小胖胖就是我
链接:https://blog.csdn.net/ywg_1994/article/details/103787294