我们在使用Axis2调用webservice的时候,在使用基础JAX-WS的时候会出现很多细节性问题,问了解决这个问题,我深入整理了一下具体的问题及解决方案,我们在网上通过查询会发现网上有两种方法,分别是RPC方式和Document方式,其实他们的实现上区别不大,主要是调用方式上,我们可以参照SOUPUI来理解就很容易了。具体我先上代码,然后在说细节。
import java.util.HashMap;
import java.util.Map;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding.ParameterStyle;
import javax.jws.soap.SOAPBinding.Style;
import javax.xml.ws.Endpoint;
@WebService(targetNamespace = "http://xxx.com", serviceName = "TestPService")
@javax.jws.soap.SOAPBinding(style=Style.DOCUMENT,parameterStyle=ParameterStyle.WRAPPED)
public class WsDemo {
public static void main(String[] args) {
WsDemo hello = new WsDemo();
Endpoint.publish("http://localhost:8091/testWS/services/TestP", hello);
System.out.println("webservice Public Success");
}
@WebMethod(action = "access")
@WebResult(name = "accessReturn")
public String access(@WebParam(name="xmldata")String xmldata) {
return "invoke success " + xmldata;
}
@WebMethod(action = "accessMap")
@WebResult(name = "accessReturn")
public Map<String,String> accessMap(String xmldata) {
Map<String,String> map=new HashMap<String,String>();
map.put("msg", xmldata);
return map;
}
}
import javax.xml.namespace.QName;
import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.databinding.utils.BeanUtil;
import org.apache.axis2.engine.DefaultObjectSupplier;
import org.apache.axis2.rpc.client.RPCServiceClient;
import org.apache.axis2.transport.http.HTTPConstants;
public class AxisUtils {
private static final AxisUtils single = new AxisUtils();
private AxisUtils() {
}
public static AxisUtils getInstance() {
return single;
}
public String rpcCall(String endpoint, String Namespace, String method, Object[] parameter, int timeout,
Class<?>[] returnDateType, String SOAPaction) {
String result = "";
RPCServiceClient client;
Object[] obj = null;
EndpointReference targetEPR = new EndpointReference(endpoint);
try {
client = new RPCServiceClient();
Options options = client.getOptions();
options.setProperty(HTTPConstants.SO_TIMEOUT, timeout);
options.setTo(targetEPR);
if (SOAPaction == null || "".endsWith(SOAPaction)) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(Constants.Configuration.DISABLE_SOAP_ACTION, true);
options.setProperties(properties);
}
options.setAction(SOAPaction);
QName opAddEntry = new QName(Namespace, method);
obj = client.invokeBlocking(opAddEntry, parameter, returnDateType);
result = obj[0].toString();
if (result == null) {
result = "";
}
} catch (AxisFault e) {
}
return result;
}
public String documentCall(String endpoint, String namespace, String method, OMElement data,
String returnElementName, int timeout, String SOAPaction) {
String result = "";
RPCServiceClient serviceClient = null;
try {
serviceClient = new RPCServiceClient();
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference(endpoint);
options.setTo(targetEPR);
options.setProperty(HTTPConstants.SO_TIMEOUT, timeout);
if (SOAPaction == null || "".endsWith(SOAPaction)) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(Constants.Configuration.DISABLE_SOAP_ACTION, true);
options.setProperties(properties);
}
options.setAction(SOAPaction);
OMElement omResult = serviceClient.sendReceive(data);
//方式一
//Class<?>[] returnTypes=new Class<?>[] {String.class};
//Object[] returnObjs= BeanUtil.deserialize(omResult, returnTypes, new DefaultObjectSupplier());
//方式二
System.out.println("====="+omResult.getFirstElement().getText());
Iterator<?> it = omResult.getChildrenWithLocalName(returnElementName);
while (it.hasNext()) {
OMElement el = (OMElement) it.next();
result = el.getText();
if (result == null) {
result = "";
}
}
serviceClient.cleanupTransport();
} catch (AxisFault e) {
try {
serviceClient.cleanupTransport();
} catch (AxisFault e1) {
}
}
return result;
}
}
上面两段代码分别是webservice和工具类,接下来上的代码分别是RPC调用和Document调用。
public class Demo1 {
public static void main(String[] args) {
String endpoint = "http://localhost:8091/testWS/services/TestP?wsdl";
String Namespace = "http://xxx.com";
String method = "access";
Object[] parameter = new Object[] { "hah" };
int timeout=30;
Class<?>[] returnDateType=new Class<?>[] {String.class};
String SOAPaction="";
String ws_rpc_return=AxisUtils.getInstance().rpcCall(endpoint, Namespace, method, parameter, timeout, returnDateType, SOAPaction);
System.out.println(ws_rpc_return);
}
}
import javax.xml.namespace.QName;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.databinding.utils.BeanUtil;
public class Demo2 {
public static void main(String[] args) {
String endpoint = "http://localhost:8091/testWS/services/TestP?wsdl";
String namespace = "http://xxx.com";
String method = "access";
String returnElementName = "";
int timeout = 30;
String SOAPaction = "";
// 方式一
Object[] params = new Object[] { "hahah" };
QName qname = new QName(namespace, method);
OMElement omElement = BeanUtil.getOMElement(qname, params, null, false, null);
// 方式二
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace qnamespace = fac.createOMNamespace(namespace, "");
OMElement methodInfo = fac.createOMElement(method, qnamespace);
OMElement valueInfo = fac.createOMElement("xmldata", fac.createOMNamespace("", ""));
valueInfo.setText("北京");
methodInfo.addChild(valueInfo);
String ws_rpc_return = AxisUtils.getInstance().documentCall(endpoint, namespace, method, omElement,
returnElementName, timeout, SOAPaction);
System.out.println(ws_rpc_return);
}
}
好了代码上全了,现在开始说细节,我么在使用RPC方式调用的时候,发布的webservice不能指定入参的参数名,如果指定了参数名是没法传参的,参数为null,Document方式有两种,第一种也是不能指定参数,但是方式二可以指定参数,但是方法和字段都需要命名空间,且参数的命名空间必须是xmlns="",否则传参也为空。以上方法是通过Axis2-adb.jar通过源码查看调用及解析方式得来,如果有喜欢深入学习建议查看源码。