1. 程式人生 > >WebService服務端與客戶端開發

WebService服務端與客戶端開發

最近客戶提出了將我們做的系統接入到他們系統之中,方便他們進行集中管理這個需求,其中主要就是運用了WebService技術來進行系統之間的接入。在此記錄一下整個WebService是如何嵌入我們系統的以及具體的開發流程。

服務端開發

新增jar包
我是使用axis2來輔助生成WebService服務端,因此需要新增相應的外掛。
首先官網下載axis2-1.6.3,解壓到資料夾中,並新增到eclipse中,window->preferences下:

具體位置

服務端的生成
首先建立服務端包以及需要的服務類,類建好之後右鍵該類,選擇Web Services->create web service.出現如下對話方塊:


直接點選完成按鈕即可生成相應的服務端。
專案結構:

釋出成功後,客戶端即可根據wsdl上的資訊進行遠端訪問。

修改wsdl中的資訊
為什麼要修改wsdl中的資訊呢?
1.因為有時候我們不想暴露有關自己專案的太多資訊,例如:專案名稱、類名、方法名以及專案的名稱空間。這時就要修改相關的配置檔案來改變wsdl中的相關資訊,達到隱藏的作用。
2.一般客戶端與服務端是2個不同的公司做的,若對方公司有要求,則必須改為要求的命名,不然訪問不同。(PS:我們當時就是被坑了)
需要修改的檔案為:server-config.wsdd
修改項為:

 <ns1:service name="UpdateAppAcctAuthorServices" provider="java:RPC" style="wrapped" use="literal">
  <ns1:operation name="updateAppAcctAuthor" qname="ns2:UpdateAppAcctAuthorServices" returnQName="ns2:UpdateAppAcctAuthorServicesReturn" returnType="xsd:string" soapAction="" xmlns:ns2="http://www.primeton.com/web"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ns1:parameter qname="ns2:RequestInfo" type="xsd:string"/> </ns1:operation> <ns1:parameter name="allowedMethods" value="updateAppAcctAuthor"/> <ns1:parameter name="wsdlPortType" value="UpdateAppAcctAuthorServices"/> <ns1:parameter name="typeMappingVersion" value="1.2"/> <ns1:parameter name="schemaQualified" value="http://www.primeton.com/web"/> <ns1:parameter name="wsdlServicePort" value="UpdateAppAcctAuthorServices"/> <ns1:parameter name="className" value="webserver.UpdateAppAcctAuthorServices"/> <ns1:parameter name="wsdlTargetNamespace" value="http://www.primeton.com/web"/> <ns1:parameter name="wsdlServiceElement" value="UpdateAppAcctAuthorServicesService"/> </ns1:service>

1.修改qname來改變wsdl中顯示的方法名
2.修改returnQName來改名wsdl中顯示的返回名
3.修改ns1:parameter qname=”ns2:RequestInfo”來改變方法中的引數名。
4.修改 ns1:parameter name=”wsdlTargetNamespace”value=”http://www.primeton.com/web”來改變名稱空間。
5.修改後就可以讓客戶端按照修改後的命名來進行訪問了。

客戶端開發

客戶端開發即為呼叫別人所寫的web服務。
所需要的jar包:

import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;

除了引入的這些jar包之外,還需要axis2 下的commons-httpclient-3.1.jar包,通過該包進行webservice通訊。

呼叫方式也有好幾種,我這裡介紹的是RPC遠端呼叫的方法。具體呼叫程式碼及註釋如下:

        String requestInfo = createRequestInfo2();

        String serviceUrl = "http://localhost:8080/com.primeton.testws/services/UpdateAppAcctSoap?wsdl";

        RPCServiceClient serviceClient = null;
        String resultString = "";
        try {
            serviceClient = new RPCServiceClient();
        } catch (AxisFault e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        Options options = serviceClient.getOptions();
        EndpointReference targetEPR = new EndpointReference(serviceUrl);
        options.setTo(targetEPR);
        // 伺服器端開放的方法名

        String wsFunction = "UpdateAppAcctSoap";

        // 要傳給伺服器開放方法的引數.
        String xmlStr = requestInfo ;

        /*在建立QName物件時,QName類的構造方法的第一個引數表示WSDL檔案的名稱空間名,
        也就是<wsdl:definitions>元素的targetNamespace屬性值*/
        QName qName = new QName("http://www.primeton.com/web", wsFunction);
        // 引數,如果有多個,繼續往後面增加即可,不用指定引數的名稱
        Object[] inputArgs = new Object[] {  };
        if(xmlStr != null && !"".equals(xmlStr)){
            inputArgs = new Object[] { xmlStr };
        }
        /*
        返回引數型別,這個和axis1有點區別
        invokeBlocking方法有三個引數,其中第一個引數的型別是QName物件,表示要呼叫的方法名;
                第二個引數表示要呼叫的WebService方法的引數值,引數型別為Object[];
                第三個引數表示WebService方法的返回值型別的Class物件,引數型別為Class[]。
                當方法沒有引數時,invokeBlocking方法的第二個引數值不能是null,而要使用new Object[]{}
                如果被呼叫的WebService方法沒有返回值,應使用RPCServiceClient類的invokeRobust方法,
                該方法只有兩個引數,它們的含義與invokeBlocking方法的前兩個引數的含義相同
        */
        Class[] returnTypes = new Class[] { String.class };
        Object[] response;
        try {
            response = serviceClient.invokeBlocking(qName, inputArgs, returnTypes);
            resultString = (String) response[0];
            System.out.println(resultString);
        } catch (AxisFault e) {
            e.printStackTrace();
        }

    }

requestInfo 是客戶端傳送的請求報文:

<?xml version="1.0" encoding="UTF-8"?>

<USERMODIFYREQ>
  <HEAD>
    <CODE></CODE>
    <SID></SID>
    <TIMESTAMP></TIMESTAMP>
    <SERVICEID></SERVICEID>
  </HEAD>
  <BODY>
    <OPERATORID>sysadmin</OPERATORID>
    <OPERATORPWD></OPERATORPWD>
    <OPERATORIP></OPERATORIP>
    <MODIFYMODE>add</MODIFYMODE>
    <USERINFO>
      <USERID>111111</USERID>
      <LOGINNO>111111</LOGINNO>
      <USERNAME></USERNAME>
      <ORGID></ORGID>
      <EMAIL>[email protected]</EMAIL>
      <MOBILE>11111111111</MOBILE>
      <PASSWORD>111111</PASSWORD>
      <STATUS></STATUS>
      <EFFECTDATE></EFFECTDATE>
      <EXPIREDATE></EXPIREDATE>
      <REMARK></REMARK>
    </USERINFO>
  </BODY>
</USERMODIFYREQ>

執行客戶端,服務端返回的報文如下:

<?xml version="1.0" encoding="UTF-8"?>

<USERMODIFYRSP>
  <HEAD>
    <CODE></CODE>
    <SID></SID>
    <TIMESTAMP></TIMESTAMP>
    <SERVICEID>SHNGDM</SERVICEID>
  </HEAD>
  <BODY>
    <MODIFYMODE>add</MODIFYMODE>
    <USERID>111111</USERID>
    <LOGINNO>111111</LOGINNO>
    <RSP>0</RSP>
    <ERRDESC></ERRDESC>
  </BODY>
</USERMODIFYRSP>