Axis2客户端调用Web服务时出现HttpClient类型转换异常
Axis2客户端HttpClient类型转换异常及解决办法
异常现象
调用第三方Web服务时出现类型转换异常:
java.lang.ClassCastException: class org.apache.http.impl.client.InternalHttpClient cannot be cast to class org.apache.commons.httpclient.HttpClient (org.apache.http.impl.client.InternalHttpClient and org.apache.commons.httpclient.HttpClient are in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @674c583e) at org.apache.axis2.transport.http.AbstractHTTPSender.getHttpClient(AbstractHTTPSender.java:529) at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:157) at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75) at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:404) at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:231) at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:443) at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:406) at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229) at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
问题代码
设置CACHED_HTTP_CLIENT属性的代码:
MyStub stub = new MyStub() ; stub._getServiceClient().getOptions().setProperty(HTTPConstants.CACHED_HTTP_CLIENT, customHttpClient); stub._getServiceClient().getServiceContext() .setProperty(HTTPConstants.CACHED_HTTP_CLIENT, customHttpClient);
异常触发点在AbstractHttpSender的以下代码行:
HttpClient httpClient = (HttpClient) msgContext.getProperty( HTTPConstants.CACHED_HTTP_CLIENT);
问题核心
Axis2默认使用的CommonsHTTPTransportSender依赖org.apache.commons.httpclient.HttpClient(旧版commons-httpclient包),而你传入的customHttpClient是org.apache.http.client.HttpClient(新版Apache HttpComponents的httpclient包,4.x及以后版本)。这两个是完全独立的类,无继承或实现关系,因此触发类型转换异常。
解决方案
方案1:改用旧版commons-httpclient创建实例
直接创建符合Axis2默认要求的旧版HttpClient实例:
import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; // 创建线程安全的HttpClient实例 MultiThreadedHttpConnectionManager connManager = new MultiThreadedHttpConnectionManager(); HttpClient customHttpClient = new HttpClient(connManager); // 配置连接超时、读取超时等参数 customHttpClient.getParams().setConnectionTimeout(5000); customHttpClient.getParams().setSoTimeout(10000); // 设置到Stub中 MyStub stub = new MyStub(); stub._getServiceClient().getOptions().setProperty(HTTPConstants.CACHED_HTTP_CLIENT, customHttpClient); stub._getServiceClient().getServiceContext().setProperty(HTTPConstants.CACHED_HTTP_CLIENT, customHttpClient);
方案2:更换Axis2传输发送器为HttpComponentsTransportSender
若希望继续使用新版HttpClient,可切换到支持新版HttpComponents的传输发送器:
方式1:通过配置文件修改
- 确保项目引入
axis2-transport-http依赖包(包含HttpComponentsTransportSender) - 修改Axis2配置文件
axis2.xml(web项目放WEB-INF/conf,客户端放classpath根目录):
<!-- 注释原有的CommonsHTTPTransportSender --> <!-- <transportSender name="http" class="org.apache.axis2.transport.http.CommonsHTTPTransportSender"> --> <!-- <parameter name="PROTOCOL">HTTP/1.1</parameter> --> <!-- <parameter name="Transfer-Encoding">chunked</parameter> --> <!-- </transportSender> --> <!-- 添加支持新版HttpClient的传输发送器 --> <transportSender name="http" class="org.apache.axis2.transport.http.HttpComponentsTransportSender"> <parameter name="PROTOCOL">HTTP/1.1</parameter> <parameter name="Transfer-Encoding">chunked</parameter> </transportSender>
- 直接传入新版HttpClient实例:
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.client.config.RequestConfig; // 创建带超时配置的新版HttpClient RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(5000) .setSocketTimeout(10000) .build(); CloseableHttpClient customHttpClient = HttpClients.custom() .setDefaultRequestConfig(requestConfig) .build(); // 设置到Stub中 MyStub stub = new MyStub(); stub._getServiceClient().getOptions().setProperty(HTTPConstants.CACHED_HTTP_CLIENT, customHttpClient); stub._getServiceClient().getServiceContext().setProperty(HTTPConstants.CACHED_HTTP_CLIENT, customHttpClient);
方式2:通过代码动态设置传输发送器
无需修改配置文件,直接在代码中替换传输发送器:
import org.apache.axis2.transport.http.HttpComponentsTransportSender; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; MyStub stub = new MyStub(); ServiceClient serviceClient = stub._getServiceClient(); // 移除默认的CommonsHTTPTransportSender serviceClient.removeTransportSender("http"); // 添加HttpComponentsTransportSender HttpComponentsTransportSender sender = new HttpComponentsTransportSender(); serviceClient.addTransportSender("http", sender); // 设置新版HttpClient CloseableHttpClient customHttpClient = HttpClients.createDefault(); serviceClient.getOptions().setProperty(HTTPConstants.CACHED_HTTP_CLIENT, customHttpClient); serviceClient.getServiceContext().setProperty(HTTPConstants.CACHED_HTTP_CLIENT, customHttpClient);
方案3:自定义适配器(不推荐)
自行编写适配器类,将新版HttpClient适配为旧版org.apache.commons.httpclient.HttpClient接口的实现。但该方式需实现旧版接口所有方法,开发成本高且易引入兼容性问题,不建议采用。
内容的提问来源于stack exchange,提问作者Jitesh
相关产品推荐
相关产品推荐

