一、Webservice可以使用的框架很多。AXIS、CXF 、JAX、XFIRE,这些框架都可以根据wsdl文件生成ws的服务器和客户端代码。
二、Ws的调用方式有三种,http post、http get、soap post。本人建议使用http post,他访问远程ws接口的速度比使用soap post要快些。象使用axis框架实现soap post方式来说,简单的接口还好,对于使用了大量代理类及带有soaphead的ws,且还要在本地生成一大堆JAVA类来和服务端对应。特别如下这种情况,axis好像无法实现。
Soaphead如下
<soapHead>
<appId>0039434454</appId>
    <pwd>67677</pwd>
</soapHead>
象这种只能根据org.apache.axis.client.Call.addHead(ElementSoapHead)来增加报头。但这个报头没有根元素,无法创建一个这种Element。
下面就如何书写客户端代码详细讲解下。
1.通过发送http post请求来调用ws。
SOAPUI是个不错的工具,他可以根据wsdl文件生成测试例子。另外重要的是,它可以生成wsdl对应的请求报文和响应报文。这样我们在调用别人写的ws时,不管多复杂的ws都可以简单的调用。首先按照SOAPUI显示的请求报文格式拼装我们的请求报文,使用java.net.HttpURLConnection对象来发送http post请求。然后使用输出流、输出流获得响应报文,再用Element解析报文得到要取的数据。示例代码如下:
JAVA类SoapInvoke:
package test;import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;public class SoapInvoke { public static void main(String[] args) {
try {
soapSpecialConnection();
} catch (Exception e) {
e.printStackTrace();
}
}

   public static void soapSpecialConnection() throws Exception
   {
   //拼装soap请求报文
       StringBuilder sb = new StringBuilder();
       StringBuilder soapHeader = new StringBuilder();
       soapHeader.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:test=\"http://test/\">");
       soapHeader.append("<soapenv:Header>");
       soapHeader.append("<spId>zhouyun</spId>");
       soapHeader.append("<spPassword>123</spPassword>");
       soapHeader.append("</soapenv:Header>");
       soapHeader.append("<soapenv:Body>");
       soapHeader.append("<test:sayHelloMiss>");
       soapHeader.append("<arg0>");
       soapHeader.append("<name>zhouyun</name>");
       soapHeader.append("</arg0>");
       soapHeader.append("</test:sayHelloMiss>");
       soapHeader.append("</soapenv:Body>");
       soapHeader.append("</soapenv:Envelope>");
       
       //设置soap请求报文的相关属性
       String url="http://localhost:8080/CXFServer/SayHelloService";
       URL u = new URL(url);
       HttpURLConnection conn = (HttpURLConnection) u.openConnection();
       conn.setDoInput(true);
       conn.setDoOutput(true);
       conn.setUseCaches(false);
       conn.setDefaultUseCaches(false);
       conn.setRequestProperty("Host", "localhost:8080");
       conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
       conn.setRequestProperty("Content-Length", String.valueOf(soapHeader.length()));
       conn.setRequestProperty("SOAPAction", "");
       conn.setRequestMethod("POST");
       //定义输出流
       OutputStream output = conn.getOutputStream();
       if (null != soapHeader) {
           byte[] b = soapHeader.toString().getBytes("utf-8");
           //发送soap请求报文
           output.write(b, 0, b.length);
       }
       output.flush();
       output.close();
       //定义输入流,获取soap响应报文
       InputStream input = conn.getInputStream();
       int c = -1;
       //sb为返回的soap响应报文字符串
       while (-1 != (c = input.read())) {
           sb.append((char)c);
       }
       input.close();
       
   }
}
2.通过axis来调用ws。
对于使用了复杂代理类的ws,我们在调用时可以使用AXIS、CXF、xfire架包来自动生成ws客户端JAVA代码。下面以axis为例,来展示。
服务器端主要JAVA代码
package test;import javax.jws.WebService;@WebService
public class SayHelloImpl implements SayHelloService { public wsResult sayHelloMr(String name) {
wsResult retObj = new wsResult(); retObj.setResultVal("Hello,mr " + name); return retObj; } public wsResult sayHelloMiss(InputClass input) { wsResult retObj = new wsResult(); retObj.setResultVal("Hello,Miss " + input.getName()); return retObj; }}
客户端:
1)新建wsdltojava.bat文件,放到C盘,文件内容如下:
set Axis_Lib=E:\axis-bin-1_4\axis-1_4\lib
set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%
set Axis_Servlet=http://localhost:8080/CXFServer/SayHelloService?wsdl
%Java_Cmd% org.apache.axis.wsdl.WSDL2Java -u %Axis_Servlet%
其中Axis_Lib为本地axis架包的路径;Axis_Servlet为本地ws的URL,这里也可以设置为此ws服务器对应的wsdl文件的路径。
2)在DOS里,执行wsdltojava.bat。在C盘根目录下就会生成JAVA客户端的代码了
3)新建一个java类Invoke,代码如下:
package test;public class invoke { public static void main(String[] args) throws Exception {
getResult(); } public static void getResult() {
try {
SayHelloImplServiceLocator svc = new SayHelloImplServiceLocator(); SayHelloService stub = svc.getSayHelloImplPort();
//调用               
//WsResult wsResult = stub.sayHelloMr("zhouyun");
InputClass inputClass=new InputClass();
inputClass.setName("zhouyun");
WsResult wsResult = stub.sayHelloMiss(inputClass);
System.out.println("结果是:" + wsResult.getResultVal()); } catch (Exception e) {
System.out.println(e);
} }}
Ps:
1.通过命令生成的java客户端代码里SayHelloImplServiceLocator类是调用ws的入口。
2.执行此类,Myelipse控制台会输出Hello,Miss zhouyun,代表调用成功。
3.象JAX、xfire架包生成的客户端代码不能实现代理类输入、输出,只可以实现简单数据类型输入、输出,象String、Map、AaaryList等等。只有axis可以实现代理类的输入、输出。