最近在开发WebService接口的时候,碰见了一个特殊的接口地址,这个接口是IBM Tivoli产品提供的WebService的接口,先来看一下这个接口地址是什么样的吧!
http://127.0.0.1:1920///cms/soap
这是它提供的一个WebService的接口地址,让我很奇怪的是,这个接口和平常的调用的WebService的接口有很多不一样的地方,但是最重要的就是URL中存在了///的字符,起初没有在意在浏览器中,和DEMO中提供的例子中都可以返回正确的SOAP响应结果,HTTP的接口测试工具也可以返回正确的响应,但是当我在项目中用HttpClient去调用的时候,发现提示404的错误了,很明显这是一个路径没有找到的错误,后来我又看了其他人用HttpClient访问的例子,返现居然好使,这让我很纳闷。于是开始进行了一番探索。
首先我发现好使的HttpClient是旧版本的,不是4这个版本的,而我使用的是HttpClient4.4这个版本的,换成了4.5也不行。用网络请求拦截工具代理拦截后,发现原本应该:
POST ///cms/soap
变成了:
POST /cms/soap
所以才会提示404,为什么HttpClient4会有这个问题,经过了调试源码后找到了问题。
当调用HttpClient的execcute的方法时,内部会调用一些执行链的类,其中有个类叫做ProtocolExec,位于org.apache.http.impl.execchain下,如下图所示:
在类中有这样一行代码:
// Re-write request URI if needed
rewriteRequestURI(request, route);
根据注释的意思是如果需要重写请求的URI,也就是在这里,将我们的///cms/soap这样的路径,重写成了/cms/soap这样的路径,以至于404的错误。
我很奇怪,注释里意思是需要的时候重写,但是这样的代码根据我的经验应该是有个字段动态判断吧,这样才可以根据需要或者不需要进行重写URI的操作,但是HttpClient4的代码中并不存在这个判断的操作,所以就是访问任何的时候,都会调用重写URI的这个方法,那么注释就没有任何的意义了,所以我在源码中的此处加上了一个判断操作,如下所示:
final HttpParams params = request.getParams();
// Re-write request URI if needed
boolean notWrite = params.getBooleanParameter("notWrite",false);
if(!notWrite){
rewriteRequestURI(request, route);
}
调用的时候,如果存在notWrite参数,不为false的时候重写,保持了原来的默认操作。然后在使用的时候能够不需要重写的时候,传递一个true的值即可,如下所示:
HttpPost post = new HttpPost(url);
HttpParams params = new BasicHttpParams();
params.setBooleanParameter("notWrite", true);
post.setParams(params);
然后把新编译后的class文件放进httpclient4的jar包中,即可将问题解决,这样当请求///cms/soap这样的路径时,就不会变成/cms/soap这样的操作了。
希望可以帮助到遇到此类问题的人们!