使用AXIS2,可以方便的构建WebService的服务器端,也可以很方便的作为Cilent,来访问别的WebService。
下面根据工作中的经历,整理了一下,作为Cilent访问WebService的要点。
根据Axis2的官方文档,Client的DataBinding方式有3种,最简单的好像是ADB,那么我就选用的ADB。
1.普通方式(http 不通过proxy,对方也没有利用SSL)
// Generate Client
RPCServiceClient serviceClient = new RPCServiceClient();
Options options = serviceClient.getOptions();
// Generate Endpoint
String webserviceurl = "http://www.abc.net/webservice/servicepage"; // for example.
EndpointReference targetEPR = new EndpointReference(webserviceurl);
options.setTo(targetEPR);
// Auto release transport.
options.setCallTransportCleanup(true);
// Generate Action
String ns = "http://www.abc.net/webservice";
String action = "getSomething";
QName opAction = new QName(ns, action);
// Generate Reqest parameters
ReqBean reqObj = new ReqBean();
reqObj.setParam1("param1");
reqObj.setParam2("param2");
Object[] opArgs = new Object[] { reqObj };
Class[] returnTypes = new Class[] { ArrayList.class };
Object[] response = null;
try {
response = serviceClient.invokeBlocking(opAction, opArgs, returnTypes);
} catch (AxisFault af) {
// Process exception.
}
ArrayList res = (ArrayList) response[0];
// Analyze the response.
// ...
返回的Response,统一先转换为ArrayList,然后进一步解析为字符串或者各个Bean。
这是最简单的访问方式。
2.通过SSL访问。(https)
大部分时候,客户端不会提前获得服务器的证书导致出错。所以需要自己更新一下通信的protocol。
官方网站上说的不甚详细,所以罗列一下代码。
2.1 生成一个新的协议工厂类:
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.HttpClientError;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
public class SSLIgnoreErrorProtocolSocketFactory implements
ProtocolSocketFactory {
private SSLContext sslcontext = null;
/**
* 不进行证明书的验证
*
* @return
*/
private static SSLContext createEasySSLContext() {
try {
SSLContext context = SSLContext.getInstance("SSL");
context.init(null, new TrustManager[] { new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} }, null);
return context;
} catch (Exception e) {
throw new HttpClientError(e.toString());
}
}
private SSLContext getSSLContext() {
if (this.sslcontext == null) {
this.sslcontext = createEasySSLContext();
}
return this.sslcontext;
}
@Override
public Socket createSocket(String host, int port) throws IOException,
UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(host, port);
}
@Override
public Socket createSocket(String host, int port, InetAddress clientHost,
int clientPort) throws IOException, UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(host, port,
clientHost, clientPort);
}
@Override
public Socket createSocket(String host, int port, InetAddress localAddress,
int localPort, HttpConnectionParams params) throws IOException,
UnknownHostException, ConnectTimeoutException {
if (params == null) {
throw new IllegalArgumentException("Parameters may not be null");
}
int timeout = params.getConnectionTimeout();
SocketFactory socketfactory = getSSLContext().getSocketFactory();
if (timeout == 0) {
return socketfactory.createSocket(host, port, localAddress,
localPort);
} else {
Socket socket = socketfactory.createSocket();
SocketAddress localaddr = new InetSocketAddress(localAddress,
localPort);
SocketAddress remoteaddr = new InetSocketAddress(host, port);
socket.bind(localaddr);
socket.connect(remoteaddr, timeout);
return socket;
}
}
}
2.2 利用上面的类,做成一个新的协议对象。(sslport根据服务器端的设定而指定,一般是443.)
Protocol protocol = null;
SSLIgnoreErrorProtocolSocketFactory socketfactory = null;
socketfactory = new SSLIgnoreErrorProtocolSocketFactory();
protocol = new Protocol("https", socketfactory, sslport);
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, protocol);
注意:HTTPConstants是利用的org.apache.axis2.transport.http.HTTPConstants类。
3. 需要通过代理服务器的情况。
这个按照官方网站的来就可以了。
3.1 生成代理属性:
HttpTransportProperties.ProxyProperties proxyProperties = new HttpTransportProperties.ProxyProperties();
proxyProperties.setProxyName(proxy_server);
proxyProperties.setProxyPort((int) (proxy_port);
HttpTransportProperties是利用的org.apache.axis2.transport.http.HttpTransportProperties
3.2 把代理属性设定给RPCServiceClient的options。
options.setProperty(HTTPConstants.PROXY, proxyProperties);
就可以通过代理服务器来访问了。
注意,使用代理服务期的注意事项:
实际工作中,我利用squid测试的时候,发现通信时,axis2默认使用chunked属性,导致不能通过squid,具体原因不明。
于是,当时用squid的时候,把chunked属性disable掉了。
options.setProperty(HTTPConstants.CHUNKED, false);
这一点,官网上没有提及,也可能是我哪里设定的不够。
以上,就是通过Axis2作为客户端访问WebService的几种情况,基本上一般的http环境差不多应该都能对付了。
当然,还有其他的通信方式,暂时在工作中没有用到。