以前一直用axis这个web service但是从来没有想过他调用.net的web serivce时会出现编码问题,为此相当的烦恼,所以改用axis2,他的毕竟会比axis1加大。
但是用到axis2时,同时又遇到了一个问题,axis2调用数据有三种方式,一般都会看到第一种RPCServiceClient此方案,但是这个方案中,居然参数无法传入,在网上查了N多记录,全部一样的,别人不知道哪里复制过来,信誓当当,没有经过自己的验证就拿出来,忽悠人,说实话,这么多年以来,我每次查资料时,都是这样的问题,别人总是原错误的代码或是有误的代码来迷了我的眼睛,现在把这段不可能成功的代码也贴出来,供大家参考,如果哪位在英文文档中找到了设置方案,希望能给我留言或是联系我的QQ:106720605
以下是RPC方式,不过没有参数的调用能成功,有参数传入,无法传入,我也没有时间一点点的去看英文api,
public class Axis2Client {
public static String target = "http://webservice.webxml.com.cn/webservices/ChinaTVprogramWebService.asmx?wsdl";
/**
* @param args
*/
public static void main(String[] args){
try{
// 获得客户端
RPCServiceClient serviceClient = new RPCServiceClient();
// 可以在该对象中设置服务端的验证信息
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference(target);
options.setTo(targetEPR);
options.setAction("http://WebXml.com.cn/getTVstationDataSet");
// 在创建QName对象时,QName类的构造方法的第一个参数表示WSDL文件的命名空间名,也就是<wsdl:definitions>元素的targetNamespace属性值
QName opAddEntry = new QName("http://WebXml.com.cn/","getTVstationDataSet");
// 参数,如果有多个,继续往后面增加即可,不用指定参数的名称
// QName arg = new QName("http://WebXml.com.cn/","getTVstationDataSet",Q);
Object[] opAddEntryArgs = new Object[] {3};
// 返回参数类型,这个和axis1有点区别
// invokeBlocking方法有三个参数,其中第一个参数的类型是QName对象,表示要调用的方法名;
// 第二个参数表示要调用的WebService方法的参数值,参数类型为Object[];
// 第三个参数表示WebService方法的返回值类型的Class对象,参数类型为Class[]。
// 当方法没有参数时,invokeBlocking方法的第二个参数值不能是null,而要使用new Object[]{}
// 如果被调用的WebService方法没有返回值,应使用RPCServiceClient类的invokeRobust方法,
// 该方法只有两个参数,它们的含义与invokeBlocking方法的前两个参数的含义相同
Class[] classes = new Class[] {Integer.class};
OMElement obj=(OMElement)(serviceClient.invokeBlocking(opAddEntry,opAddEntryArgs, classes)[0]);
System.out.println("============"+obj.toStringWithConsume());
} catch (Exception e) {
e.printStackTrace();
}
}
}
据我的经验应该就是哪里少了一个设置,可是目前没有办法找到。国内也没有哪位把研究成果公布过。
而后就产生了第二种调用方案用serverClient但是这个方案有个最大的缺点,所有的返回的都是xml都要进行解析,实话omelement相当的不好用,不过我还是封装了一个方案,以后哪位可以复制过去学习一下
/**
* 用axis2通过document方式进行调用,返回xml文件,所有数据要进行xml解析
* @author storm
* @param target 目标地址
* @param tarAction targetAction此处在文件可找到
* @param namespace
* @param method 调用的方法名
* @param args 参数其中如无参数用null进行调用,如有参数用treeMap 其中name就是参数名,value是参数的值
* @return 返回OMElment此为xml对象的接口
* @throws Exception
*/
public OMElement getServiceReturnXML(String target,String tarAction,String namespace,String method,TreeMap<String, String> args)throws Exception{
EndpointReference targetEPR = new EndpointReference(target);
ServiceClient sender = new ServiceClient();
Options options = new Options();
options.setTo(targetEPR);
options.setSoapVersionURI(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
if(tarAction!=null&&!tarAction.equals("")){
options.setAction(tarAction);
}
sender.setOptions(options);
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs = fac.createOMNamespace(namespace, "");
OMElement data = fac.createOMElement(method, omNs);
if(args!=null){
for(Iterator iterator = args.keySet().iterator();iterator.hasNext();){
String name = iterator.next().toString();
String value = args.get(name).toString();
OMElement inner = fac.createOMElement(name, omNs);
inner.setText(value);
data.addChild(inner);
}
}
OMElement result = sender.sendReceive(data);
return result;
}
到最后就是最合理的,也是最方案方案,用存根式来完成调用,以前两个项目都是java的时候我会采用cxf 这样根本没有调用webservice的感觉,好像只是使用本地的class
这个存根也有这样的感觉了,存根就要先用工具把这个接口生成java的根
先配置AXIS2_HOME这个路径,注此路径不要配置到bin这个文件夹上,不然会不成功的,
然后就直接使用wsdl2java -uri http://xxxxxxxxxxx?wsdl 注明:后面要加上wsdl
这样就会生成一个src文件夹,里面有你要的接口与class
try {
ChinaTVprogramWebServiceStub stub = new ChinaTVprogramWebServiceStub();
GetTVchannelDataSet getTV = new GetTVchannelDataSet();
getTV.setTheTVstationID(3);
System.out.println(stub.getTVchannelDataSet(getTV).getGetTVchannelDataSetResult().getExtraElement().toStringWithConsume());
} catch (AxisFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XMLStreamException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
然后写上的代码先new出存根,每二行把你要调用的方法也new 出来,第三行,把参数置入,第四行调回数据,就这么简单而且数据的回来是会和你要求的数据一致。
这样完成了axis2的使用。