Axis2开发WebService服务端及客户端

分类: 系统运维

参考  http://www.ibm.com/developerworks/webservices/library/ws-apacheaxis/index.html

下载axis2-1.5.4-bin.zip文件并解压。设置axis2的环境变量 " AXIS2_HOME"

服务端

We will generate the service components for the web service. For this we will use the standard Axis2's WSDL2Java command. We will use Axis2 Data binding Framework (ADB) as the data binding framework (you are free to choose any data binding framework which Axis2 supports). For generating the server-side components of the web service, execute the following command in the same command prompt window. 

利用 wsdl 文件生成服务端代码

  1. %AXIS2_HOME%\bin\WSDL2Java -uri StockQuoteService.wsdl -d adb -s -ss -sd -ssi -o service

WSDL2Java命令参数说明: 
  -uri  指定*.wsdl文件,可以带具体路径;  
  -p  指定生成代码的包名 
  -d  使用不同的数据绑定方法;  
adb , xmlbeans  

  -o  指定生成代码放置的路径; 
  -ss 表示要生成服务端代码;  
  -ssi 表示要生成代码中,先生成接口类,再生成实现类;
 


新建web工程(服务端)  结构如下

  1. WebContent
  2.   |-- WEB-INF
  3.        |-- classes    
  4.        |-- lib                        添加 axis2 的jar包
  5.        |-- services        固定目录名称   将生成resources目录下的文件放入 
  6.        |     |-- StockQuoteService    目录名称可随意取
  7.        |           |-- META-INF
  8.        |                 |-- services.xml      固定名称 
  9.        |                 |-- StockQuoteService.wsdl   用于发布的wsdl文件
  10.        |-- web.xml
  11.        |-- weblogic.xml


编辑web.xml加入如下代码: 

  1.  
        AxisServlet
        org.apache.axis2.transport.http.AxisServlet
     

     
        AxisServlet
        /services/*
     

weblogic.xml 适用于weblogic 服务器
  解决 java.lang.NoSuchMethodError: javax.xml.namespace.QName.(Ljava/lang/String;
Ljava/lang/String;Ljava/lang/String;)V 问题

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN" "http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">

  3. <weblogic-web-app>

  4.   <container-descriptor>
  5.     true
  6.   </container-descriptor>

  7.   <context-root>StockQuoteWS</context-root>
  8. </weblogic-web-app>
打包发布  http://localhost:8080/StockQuoteWS/services/StockQuoteService?wsdl


客户端  调用三种方法  前两种不生成客户端代码  但不太好用 

点击(此处)折叠或打开

  1. package samples.quickstart.client;

  2. import javax.xml.namespace.QName;
  3. import org.apache.axiom.om.OMAbstractFactory;
  4. import org.apache.axiom.om.OMElement;
  5. import org.apache.axiom.om.OMFactory;
  6. import org.apache.axiom.om.OMNamespace;
  7. import org.apache.axis2.AxisFault;
  8. import org.apache.axis2.addressing.EndpointReference;
  9. import org.apache.axis2.client.Options;
  10. import org.apache.axis2.client.ServiceClient;
  11. import org.apache.axis2.rpc.client.RPCServiceClient;
  12. import samples.quickstart.StockQuoteServiceStub;
  13. import samples.quickstart.xsd.GetPrice;
  14. import samples.quickstart.xsd.GetPriceResponse;

  15. public class StockQuoteClient {

  16.   /**
  17.    * 方法一: 
  18.    * 应用rpc的方式调用 这种方式就等于远程调用,
  19.    * 即通过url定位告诉远程服务器,告知方法名称,参数等, 调用远程服务,得到结果。
  20.    * 使用 org.apache.axis2.rpc.client.RPCServiceClient类调用WebService
  21.    * 
  22.     【注】:
  23.     
  24.         如果被调用的WebService方法有返回值 应使用 invokeBlocking 方法 该方法有三个参数
  25.           第一个参数的类型是QName对象,表示要调用的方法名;
  26.           第二个参数表示要调用的WebService方法的参数值,参数类型为Object[];
  27.             当方法没有参数时,invokeBlocking方法的第二个参数值不能是null,而要使用new Object[]{}。
  28.           第三个参数表示WebService方法的 返回值类型的Class对象,参数类型为Class[]。
  29.         
  30.         
  31.         如果被调用的WebService方法没有返回值 应使用 invokeRobust 方法 
  32.           该方法只有两个参数,它们的含义与invokeBlocking方法的前两个参数的含义相同。

  33.         在创建QName对象时,QName类的构造方法的第一个参数表示WSDL文件的命名空间名,
  34.         也就是 元素的targetNamespace属性值。
  35.    * 
  36.    */
  37.   public static void testRPCClient() {
  38.     try {
  39.       // axis1 服务端
  40. // String url = "http://localhost:8080/StockQuote/services/StockQuoteServiceSOAP11port?wsdl"; 
  41.       // axis2 服务端
  42.       String url = "http://localhost:8080/axis2ServerDemo/services/StockQuoteService?wsdl";

  43.       // 使用RPC方式调用WebService
  44.       RPCServiceClient serviceClient = new RPCServiceClient();
  45.       // 指定调用WebService的URL
  46.       EndpointReference targetEPR = new EndpointReference(url);
  47.       Options options = serviceClient.getOptions();
  48.       //确定目标服务地址
  49.       options.setTo(targetEPR);
  50.       //确定调用方法
  51.       options.setAction("urn:getPrice");

  52.       /**
  53.        * 指定要调用的getPrice方法及WSDL文件的命名空间 
  54.        * 如果 webservice 服务端由axis2编写 
  55.        * 命名空间 不一致导致的问题
  56.        * org.apache.axis2.AxisFault: java.lang.RuntimeException: Unexpected subelement arg0 
  57.        */
  58.       QName qname = new QName("http://quickstart.samples/xsd", "getPrice");
  59.       // 指定getPrice方法的参数值
  60.       Object[] parameters = new Object[] { "13" };
  61.       
  62.       // 指定getPrice方法返回值的数据类型的Class对象
  63.       Class[] returnTypes = new Class[] { double.class };

  64.       // 调用方法一 传递参数,调用服务,获取服务返回结果集
  65.       OMElement element = serviceClient.invokeBlocking(qname, parameters);
  66.       //值得注意的是,返回结果就是一段由OMElement对象封装的xml字符串。
  67.       //我们可以对之灵活应用,下面我取第一个元素值,并打印之。因为调用的方法返回一个结果
  68.       String result = element.getFirstElement().getText();
  69.       System.out.println(result);

  70.       // 调用方法二 getPrice方法并输出该方法的返回值
  71.       Object[] response = serviceClient.invokeBlocking(qname, parameters, returnTypes);
  72.       // String r = (String) response[0];
  73.       Double r = (Double) response[0];
  74.       System.out.println(r);

  75.     } catch (AxisFault e) {
  76.       e.printStackTrace();
  77.     }
  78.   }

  79.   /**
  80.    * 方法二: 应用document方式调用
  81.    * 用ducument方式应用现对繁琐而灵活。现在用的比较多。因为真正摆脱了我们不想要的耦合
  82.    */
  83.   public static void testDocument() {
  84.     try {
  85.       // String url = "http://localhost:8080/axis2ServerDemo/services/StockQuoteService";
  86.       String url = "http://localhost:8080/StockQuote/services/StockQuoteServiceSOAP11port?wsdl";

  87.       Options options = new Options();
  88.       // 指定调用WebService的URL
  89.       EndpointReference targetEPR = new EndpointReference(url);
  90.       options.setTo(targetEPR);
  91.       // options.setAction("urn:getPrice");

  92.       ServiceClient sender = new ServiceClient();
  93.       sender.setOptions(options);
  94.       
  95.       
  96.       OMFactory fac = OMAbstractFactory.getOMFactory();
  97.       String tns = "http://quickstart.samples/";
  98.       // 命名空间,有时命名空间不增加没事,不过最好加上,因为有时有事,你懂的
  99.       OMNamespace omNs = fac.createOMNamespace(tns, "");

  100.       OMElement method = fac.createOMElement("getPrice", omNs);
  101.       OMElement symbol = fac.createOMElement("symbol", omNs);
  102.       // symbol.setText("1");
  103.       symbol.addChild(fac.createOMText(symbol, "Axis2 Echo String "));
  104.       method.addChild(symbol);
  105.       method.build();
  106.       
  107.       OMElement result = sender.sendReceive(method);

  108.       System.out.println(result);

  109.     } catch (AxisFault axisFault) {
  110.       axisFault.printStackTrace();
  111.     }
  112.   }

  113.  /**
  114.   * 为SOAP Header构造验证信息, 
  115.   * 如果你的服务端是没有验证的,那么你不用在Header中增加验证信息
  116.   * 
  117.   * @param serviceClient
  118.   * @param tns 命名空间 
  119.   * @param user 
  120.   * @param passwrod
  121.   */
  122.   public void addValidation(ServiceClient serviceClient, String tns , String user, String passwrod) {
  123.     OMFactory fac = OMAbstractFactory.getOMFactory();
  124.     OMNamespace omNs = fac.createOMNamespace(tns, "nsl");
  125.     OMElement header = fac.createOMElement("AuthenticationToken", omNs);
  126.     OMElement ome_user = fac.createOMElement("Username", omNs);
  127.     OMElement ome_pass = fac.createOMElement("Password", omNs);
  128.     
  129.     ome_user.setText(user);
  130.     ome_pass.setText(passwrod);
  131.     
  132.     header.addChild(ome_user);
  133.     header.addChild(ome_pass);

  134.     serviceClient.addHeader(header);
  135.   }

  136.   
  137.   /**
  138.    * 方法三:利用axis2插件生成客户端方式调用
  139.    * 
  140.    */
  141.   public static void testCodeClient() {
  142.     try {
  143.       String url = "http://localhost:8080/axis2ServerDemo/services/StockQuoteService";
  144.       StockQuoteServiceStub stub = new StockQuoteServiceStub(url);
  145.       GetPrice request = new GetPrice();
  146.       request.setSymbol("ABCD");
  147.       GetPriceResponse response = stub.getPrice(request);
  148.       System.out.println(response.get_return());
  149.     } catch (org.apache.axis2.AxisFault e) {
  150.       e.printStackTrace();
  151.     } catch (java.rmi.RemoteException e) {
  152.       e.printStackTrace();
  153.     }

  154.   }

  155.   public static void main(String[] args) {
  156.      StockQuoteClient.testRPCClient();
  157. // StockQuoteClient.testDocument();
  158.     // StockQuoteClient.testCodeClient();

  159.   }
  160. }





利用 axis2 的wsdl2java.bat生成客户端程序

%AXIS2_HOME%\bin\ wsdl2java  -uri StockQuoteService.wsdl  -d adb  -p axis2.service.server  -o  client  -u
   其中-uri 参数指定了wsdl 文件的路径,可以是本地路径,也可以是网络路径。-p 参数指定了生成的Java 类的包名,-o 参数指定了生成的一系列文件保存的根目录。加上可选参数  -u Unpacks the databinding classes  避免生成的ServiceStub类特别大 在执行完上面的命令后,读者就会发现在当前目录下多了个 client 目录, 可以找到一个HelloServiceStub.java 文件,该文件复杂调用WebService ,读者可以在程序中直接使用这个类。

其中HelloServiceStub.java是客户端程序,HelloServiceCallbackHandler.java是异步客户端程序。


Axis2 客户端最少依赖包

  1. activation-1.1.jar
  2. axiom-api-1.2.4.jar
  3. axiom-impl-1.2.4.jar
  4. axis2-adb-1.2.jar
  5. axis2-kernel-1.2.jar
  6. commons-codec-1.3.jar
  7. commons-httpclient-3.0.1.jar
  8. commons-logging-1.1.jar
  9. stax-api-1.0.1.jar
  10. wsdl4j-1.6.2.jar
  11. wstx-asl-3.2.1.jar
  12. XmlSchema-1.3.1.jar

你可能感兴趣的:(web,service)