Delphi和 C# Java實現webservice架構 1,2

來源:互聯網
上載者:User

http://www.360doc.com/content/070519/12/10584_508473.html

http://www.cnblogs.com/jin20000/archive/2009/01/08/1371720.html

  用
java建立webservice是快捷的,但是用java在製作用戶端的感覺上總是不如
Delphi的(個人感覺,java高手們不要笑話我),那我們就用java實現webservice的服務端程式,delphi製作用戶端。
   
    一.環境搭建

    
    jdk和tomcat的安裝和配置我在這裡不進行行介紹了。說明一點我的tomcat是安裝在D:/tomcat,設定連接埠是8099。

 

    安裝Axis
     1.可以從http://ws.apache.org/axis/
下載axis的最新版本,我使用的是axis1.2。
     2.解壓縮axis-bin-1_2beta.zip,將axis-1_2beta目錄中webapps下的axis目錄全部拷貝到tomcat的安裝目錄中webapps下。
     3.將axis/lib中的所有jar檔案都添加到classpath系統變數中。

     注(使用者需根據自己的安裝路徑變更):
     
      .;
      d:/tomcat/webapps/axis/WEBINF/lib/axis.jar;
      d:/tomcat/webapps/axis/WEB-INF/lib/saaj.jar;
      d:/tomcat/webapps/axis/WEB-INF/lib/commons-logging.jar;
      d:/tomcat/webapps/axis/WEB-INF/lib/commons-discovery.jar;
      d:/tomcat/webapps/axis/WEB-INF/lib/wsdl4j.jar;
      d:/tomcat/webapps/axis/WEBINF/lib/jaxrpc.jar;
   

     4.啟動tomcat訪問http://cbf107:8099/axis/index.html
(這裡使用的主機名稱和連接埠號碼和使用的tomcat所配置一致)。
    可以見到如下頁面:

     
 

    二.Web Service服務端開發

  
    寫一個java小程式:

    
     public class Test{
       public int add(int p1, int p2) {
         return p1 + p2;
       }
       public int subtract(int p1, int p2) {
         return p1 - p2;
       }
     }
    

    在D:/Tomcat/webapps/axis 目錄下建立一個test檔案夾,將它儲存在裡面,注意:尾碼名改為jws,也就是Test.jws 。
  
    在瀏覽器裡訪問:http://cbf107:8099/axis/test/Test.jws
可以看到

    
 

    點擊“Click to see the WSDL”出現

    
 
    將這頁另存新檔xml文檔(我們在使用delphi製作用戶端的時候會使用)

    
 

    三.delphi實現Web Service用戶端開發

    開啟delphi建立工程,在form上放置兩個edit和兩個button,button的name命名為
btnadd和btnsubtract,caption命名為add和subtract。

    再file->new->other,選擇webservice裡的WSDL importer

    

    在search UDDI..裡選擇前面我們儲存的那個xml檔案,點擊next最後finish

    
    

    
 
    
    全部儲存,我們發現delphi的工程中多了test1.pas
   
    
 

    開啟發現有這樣一段介面申明:
      Test = interface(IInvokable)
        ['{52882FF0-46E2-6644-A77B-CE714D4CBFD5}']
        function  add(const p1: Integer; const p2: Integer): Integer; stdcall;
        function  subtract(const p1: Integer; const p2: Integer): Integer; stdcall;
      end;
    
    那我們可以直接調用這個介面了,這時候我們回到介面,從delphi的webservices面版中托放一個soap到form上。

    
 

設定屬性

 

    
 

最後我們可以完成我們的代碼了:
    1.在uses裡添加test1
因為我們要引用這個單元。
    2.添加全域變數t1:test;
(t1是一個test介面)
    3.為兩個button添加click事件

    procedure TForm1.btnaddClick(Sender: TObject);
    var
      i,j,z:integer;
    begin
      i:=strtoint(edit1.Text);
      j:=strtoint(edit2.Text);
      t1:=(HttPRIO1 as test);
      z:=t1.add(i,j);
      t1._Release;
      showmessage(inttostr(z));
    end; 



    procedure TForm1.btnsubstractClick(Sender: TObject);
    var
      i,j,z:integer;
    begin
      i:=strtoint(edit1.Text);
      j:=strtoint(edit2.Text);
      t1:=(HttPRIO1 as test);
      z:=t1.subtract(i,j);
      t1._Release;
      showmessage(inttostr(z));
    end;

    4.F9運行程式進行測試
    
    
 

    
 

    看我們有用delphi實現了java寫的那段程式,不是嗎。

    5.也許到這裡你認為應該已經完成了,沒錯!不過對webservice還不夠瞭解的
 朋友你再修改一下那個java程式,也就是將Test.jws裡的這個方法 

      public int add(int p1, int p2) {
        return p1 + p2;
      }


      改為

      public int add(int p1, int p2) {
        return p1 + p2+10;
      }


    再運行一下你的用戶端程式看看。

    四.註:unit1的所有代碼

    unit Unit1;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Rio, SOAPHTTPClient,Test1;

    type
      TForm1 = class(TForm)
        HTTPRIO1: THTTPRIO;
        Edit1: TEdit;
        Edit2: TEdit;
        btnadd: TButton;
        btnsubstract: TButton;
        procedure Edit2KeyPress(Sender: TObject; var Key: Char);
        procedure btnaddClick(Sender: TObject);
        procedure btnsubstractClick(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;
      t1:test;

    implementation

    {$R *.dfm}

    //這裡是為了讓 兩個edit只能輸入數字,edit1的onkeypress直接調用這個就可以了。
    procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char); 
    begin
      if key in ['0'..'9']=false then
        key:=#0;
    end;

    procedure TForm1.btnaddClick(Sender: TObject);
    var
      i,j,z:integer;
    begin
      i:=strtoint(edit1.Text);
      j:=strtoint(edit2.Text);
      t1:=(HttPRIO1 as test);
      z:=t1.add(i,j);
      t1._Release;
      showmessage(inttostr(z));
    end;

    procedure TForm1.btnsubstractClick(Sender: TObject);
    var
      i,j,z:integer;
    begin
      i:=strtoint(edit1.Text);
      j:=strtoint(edit2.Text);
      t1:=(HttPRIO1 as test);
      z:=t1.subtract(i,j);
      t1._Release;
      showmessage(inttostr(z));
    end;

    end.

 

對WebService的使用和調試做一下記錄。備忘。

    因使用JB2005+AXIS 發布WebService,總有一些奇奇怪怪的問題,故使用JB9。

(一)使用 JB9+AXIS 發布 WebService 服務

   
1.建立Project--Project,建立Web--Web Application;

2.建立Web Service--Web Services Configuration;

3.WebApp選擇剛建立的Web Application的名字,其他預設;

4.建立WebService服務端的類(test.java)。

    -----------------------------

    public class test {
      private static int a;
      private static int b;

      public test() {
      }

      public void setA(int x) {
        this.a=x;
      }

      public void setB(int y) {
         this.b=y;
      }

      public int getSum() {
        int c=a+b;
        //System.out.println("a:"+a);
        //System.out.println("b:"+b);
        //System.out.println("c:"+c);
        return c;
      }
    }

    -----------------------------

5.發布 WebService 服務

    (1)右擊要發布的類,選擇“Export as a Web Service”;

    (2)如果勾選了“Generate client stub”,則發布後同時產生用戶端的類及介面測試類別。可以不勾擇此項;

    (3)“Deploy scope”中可以選擇該項為“Session”,其他預設;

    (4)“Selection mode”中選擇“Allow selected methods”,然後在“Methods in”中選中類要發布的介面方法。可多選。

    (5)其他預設,點擊“Finish”完成發布後,自動產生WSDL(Web Service Description Language)檔案。

6.注意

    類的屬性使用了private static修飾符。如“private static int a”。

    類的方法不能使用static修飾符,如“public int getSum()”,因為靜態類方法是不能發布為WebService介面的。

 

(二)使用 Delphi7 編寫 WebService 的用戶端

1.建立Project & Application;

2.New-Other-WebService-WSDL Importer,選擇WebService服務的WSDL描述檔案,也可選擇WSDL檔案的URL;

3.單擊“Finish”按鈕,產生WSDL檔案對應*.pas單元檔案;

    其內容大致如下:

    ------------------------------------------------------
test = interface(IInvokable)
      ['{787CE852-EF00-40BA-5802-9BF9DFBF79F0}']
        procedure setA(const a: Integer); stdcall;
        procedure setB(const b: Integer); stdcall;
        function getSum: Integer; stdcall;
      end;

    function Gettest(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): test;

    implementation

    function Gettest(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): test;
    const
      defWSDL = 'http://127.0.0.1:8088/test/services/test?wsdl';
      defURL = 'http://127.0.0.1:8088/test/services/test';
      defSvc = 'testService';
      defPrt = 'test';
    var
      RIO: THTTPRIO;
    begin
      Result := nil;

      if (Addr = '') then
      begin
        if UseWSDL then
          Addr := defWSDL
        else
          Addr := defURL;
      end;

      if HTTPRIO = nil then
        RIO := THTTPRIO.Create(nil)
      else
        RIO := HTTPRIO;

      try
        Result := (RIO as test);
        if UseWSDL then
        begin
          RIO.WSDLLocation := Addr;
          RIO.Service := defSvc;
          RIO.Port := defPrt;
        end else
          RIO.URL := Addr;
      finally
        if (Result = nil) and (HTTPRIO = nil) then
          RIO.Free;
      end;
    end;

    initialization
      InvRegistry.RegisterInterface(TypeInfo(test), 'http://127.0.0.1:8088/test/services/test', 'UTF-8');
      InvRegistry.RegisterDefaultSOAPAction(TypeInfo(test), '');

    end.

    ------------------------------------------------------

4.建議:儲存由WSDL檔案產生的*.pas單元檔案時要重新命名(webtest.pas),最好不使用預設名字;

5.Delphi7編寫的WebService用戶端調用代碼:

    -----------------------------
    uses webtest;

    var atest: test; //test類
        sum:Integer;
    begin
       atest:=Gettest(); //要uses wsdl對應*.pas單元檔案。
       atest.setA(1);
       atest.setB(2);
       sum:=atest.getSum();
       ShowMessage(IntToStr(sum));
    end;

    -----------------------------

6.注意

   如果服務端類的屬性沒有加static描述,則Delphi7編寫的用戶端使用setA()、setB()後再getSum()時不能得到正確的結果。

   因為WebService是不需連線的,每次使用類方法時均得到一個新的對象應用,setA()、setB()後再getSum()操作不是針對同一個對象的。

   但加上static後,所有的對象共同使用類的同一個值。如此即可。

   另外,如果在JB9+AXIS發布WebService時,“Deploy scope”中選擇的是“Session”,而不是預設的“Request”,

   在服務端類的屬性即使不使用static約束,在Delphi的用戶端使用setA()、setB()後再getSum(),也是可以得到正確的傳回值。

   神奇。^_^

7.建議

   本例只做測試和解決問題。如果要給WebService服務端傳遞資料,最好在介面方法中使用參數。

   如修改為getSum(int x,int y)後再發布介面,這個即可使用一個介面方法就可以完成操作,而不必先使用set方法傳遞參數資料。

 

(三)使用JB9編寫 WebService 的用戶端

1.建立Project--Project;

2.建立Web Service--Import a Web Service;

3.在WSDL URL中選擇wsdl檔案的URL,也可選擇WebService服務的WSDL描述檔案;

4.因為是建立WebService的用戶端,所以“Generate server-side classes”選擇可以不勾選;

5.在“Package options”中可以修改“Name”為合適的名字;

6.其餘選擇預設值,單擊“Finish”產生用戶端的jajva類檔案。一般是6個檔案,有其自己的命名規則。可參看JB。

7.JB9編寫的WebService用戶端測試類別

    -----------------------------

    public class client {

      public client() {
      }

      public static void main(String[] args) {
        try {
          TestService service = new TestServiceLocator();
          Test aClient = service.gettest();
          aClient.setA(1);
          aClient.setB(2);
          int sum = aClient.getSum();
          System.out.println("Sum is:"+sum);
        }
        catch (Exception e) {
          System.err.println("Execution failed. Exception: " + e);
        }
      }

    -----------------------------

8.注意

    如果服務端類的屬性沒有加static描述,則JB編寫的用戶端使用setA()、setB()後再getSum()時亦不能得到正確的結果。

    建議使用帶參數的介面方法來傳遞參數資料。避免使用set方法。

(四)使用Delphi7調用C#編寫的WebService服務

    Delphi7編寫的用戶端調用C#編寫的WebService服務時,如果函數中傳遞的參數為漢字時,可能出現亂碼現象。

    在網上搜尋了一些資料,找到解決辦法:將HTTPRIO的UseUTF8InHeader屬性改為true即可。

    即編輯由WSDL檔案產生的*.pas單元檔案,在Get函數中增加一句:RIO.HTTPWebNode.UseUTF8InHeader:=True。
   
    代碼片斷大致如下:

    ------------------

      try
        RIO.HTTPWebNode.UseUTF8InHeader:=True; //添加一句,修改編碼方案。
        Result := (RIO as test);
        if UseWSDL then
        begin
          RIO.WSDLLocation := Addr;
          RIO.Service := defSvc;
          RIO.Port := defPrt;
        end else
          RIO.URL := Addr;
      finally
        if (Result = nil) and (HTTPRIO = nil) then
          RIO.Free;
      end;

    ----------------

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.