以前一直用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的使用。