下載 Apache Axis 用來實現 SOAP( 簡單對象訪問協議 ) http://ws.apache.org/axis/

目前最穩定的版本是 1.1

?

SOAP 是用于在分散的或者分布式的環境中交換信息的一個輕量級協議。 SOAP 基于 XML ,由三部分組成:一個必須的 SOAP 封裝,一個可選的 SOAP 頭和一個必須的 SOAP 體。

通常情況下, SOAP = HTTP + RPC + XML 即: SOAP HTTP 作為底層通信協議,以 RPC 作為交互方式,以 XML 作為數據傳送的格式。

?

Web Service 開發所需要掌握的技能:

JAVA ,線程,同步, Classloader ,錯誤排除,知道 NPE(NullPointerException) 和其他一些常見的錯誤,并能夠處理, Servlet ,如何發布 Web 應用到應用服務器 (Tomcat )

TCP/IP,socket API XML...多得嚇人啊!要學習啊:(

?

1 安裝配置 Axis

?

~~安裝 Tomcat 4.X 以上版本 (4.X 后的版本都帶 XML 的解析器 )

~~解壓 Axis1.1.zip 包,找到 webapps 目錄下的 axis 文件夾,拷貝 axis 文件夾到 Tomcat 中的 webapps 文件夾下。

~~將 Tomcat 中的 axis 目錄下的 WEB-INF\lib 中的所有的文件 copy Tomcat common\lib 目錄中。 ( 以后凡是要在 axis lib 中添加 jar 文件,都要 copy 一份到 Tomcat common\lib 目錄下 )

~~我的電腦 -> 屬性 -> 高級 -> 環境變量 -> 系統變量中添加:

AXIS_HOME
%TOMCAT_HOME%\webapps\axis(TOMCAT
的目錄
)

AXIS_LIB
%AXIS_HOME%\lib

AXISCLASSPATH
%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery.jar; %AXIS_LIB%\commons-logging.jar;%AXIS_LIB%\jaxrpc.jar; %AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar; %AXIS_LIB%\xml-apis.jar;%AXIS_LIB%\xercesImpl.jar

修改 CLASSPATH ,在末尾加上:
%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery.jar; %AXIS_LIB%\commons-logging.jar;%AXIS_LIB%\jaxrpc.jar; %AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar; %AXIS_LIB%\xml-apis.jar;%AXIS_LIB%\xercesImpl.jar

?

注意檢查 CLASSPATH 是否正確:(有些軟件會在用戶變量區設置一個 classpath ,會有影響,如 :XMLSPY

DOS 方式下

輸命令: Echo %CLASSPATH%

~~檢查配置:

啟動 Tomcat ,訪問 http://localhost:8080/axis/

?

驗證 axis 的是否工作: http://localhost:8080/axis/happyaxis.jsp 如果正常顯示表示正常。

?

?

上圖中 倒數第 3 行字“ The core axis libra…. ”,要保證 core axis libraries are present ,如果有任何 core library is missing ,就到其提供的相應的鏈接上找到對應的 jar 文件,并 copy tomcat 目錄里面的 axis 文件夾 WEB-INF\lib 中,別忘了 Tomcat 自己的 common\lib copy 一份。

直到所有的 core library are present.

?

好啦基本上都配置好了。現在我們開始做一個有點模樣的 web Service 的例子啦。一步一步來:)

?

目標:模擬一個銀行存取款系統,存取款的具體實現作為服務來提供

Axis 提供了兩種服務發布方式,一種是即時發布( Instant Deployment ),一種是定制發布( Custom Deployment )。

1. 使用即時發布 Java Web Service(JWS)

  “對即時發布的支持是 Axis 的特色之一,使用即時發布使用戶只需有提供服務的 Java 類的源代碼,即可將其迅速發布成 Web 服務。每當用戶調用這類服務的時候, Axis 會自動進行編譯,即使服務器重啟了也不必對其做任何處理,使用非常簡單快捷。”

使用即時發布首先需要一個實現服務功能的 Java 源文件,將其擴展名改為 .jws Java Web Service 的縮寫),然后將該文件放到 Tomcat 下面的 webapps\axis 目錄下即可。但是 JWS web 服務發布是一個很簡單的 Web 服務發布方式,在頁面中你不能使用包,而且由于代碼是在運行期被編譯的,所以在部署之后,你也很難找到錯誤所在。

就是不好羅,但是我們還是來看一個例子:大家在 Tomcat webapps\axis 下找到 Calculate.jws 文件,然后打開看看。不用編譯的。

發布吧: http://localhost:8080/axis/Distance.jws?wsdl 如果你看到下面的 WSDL 描述表示你已經發布成功啦:

?

?

怎么使用這個服務呢?大家到

Tomcat 5.0\webapps\axis\WEB-INF\classes\samples\userguide\example2

里面是不是看到一個 CalcClient.class 的文件啊?這個文件就是對應的 axis 提供的 calculate 的客戶端的例子。在 dos 方式,到 Tomcat 5.0\webapps\axis\WEB-INF\classes\ 目錄下:

java samples.userguide.example2.CalcClient add 3 4

是不是得到 7 了啊?如果出現 NoDefClass 的錯誤的話就用 echo 檢查各個環境變量吧。一般都錯在這里。

Calculator 對應的源代碼在下載的 axis.zip 里面的 samples\userguide\example2 里面。

?

2. 使用定制發布 Web Service Deployment Descriptor(WSDD)

  “即時發布是一項令人激動的技術,它使 Web 服務的開發變得如此簡單;然而即時發布并不總是最好的選擇,比如有些應用系統是第三方提供的,我們沒有購買源代碼,只有 .class 文件,但我們又希望將這個應用系統的一些功能對外發布成 Web 服務,使其能夠在更大范圍內產生作用,這個時候即時發布技術就無能為力了。此外,即時發布技術并不靈活,無法進行更多的服務配置,這使得它并不能滿足一些特定系統的需求。”

????? 好啦 到我們啦,我先不說定制發布有什么好,大家先往下看,自然會有體會的:)

首先給出我們的模擬銀行存取款的 java 文件:

Account.java

?

package com.duckur;

public class? Account

{

????????? /*************************************************************

???????? ?/* 從隨機數中獲取帳戶(一次性有效) */

???????? ?public static int fund = (int)(java.lang.Math.random()*10000);

???????? ?// 模擬,大家可以從文件中讀取數據,或者從數據庫中取出這個 fund

?????????? /*************************************************************

?????????? ?/* 檢查輸入的有效性 */

????????? ?public boolean checkInput(int money)// 只能取整數

????????? ?{

?????????? ?if(money > fund)

??????????? {

???????????????? ?return false;

???????????? }

???????????? else

??????????? ?{

???? ??????????? return true;

?????????????? }

?????????? ?}

????????? ?/*************************************************************

?????????? /* 存款 */

?????????? public int deposit(int money)

???????? ?{

???????????????? fund? = fund + money;

?????????????? ?return fund;

?????????? }

????????? /*************************************************************

????????? /* 取款 */

????????? public int withdraw(int money)

????????? {

??????????????????? if(checkInput(money))

???????????????????? {

????????????????????????????? fund = fund - money;

???????????????????? }

???????????????????? return fund;

?????????? }

????????? /*************************************************************

?????????? /* 獲取當前的帳戶值 */

?????????? public int getAccount()

?????????? {

???????????????????? return fund;

????????? }

}

?

??? 然后編譯,通過后生成的class文件應該放在Tomcat下的webapps\axis\WEB-INF\com\duckur\下面。

下面發布:

???? 在Tomcat下的webapps\axis\WEB-INF\com\duckur\目錄下新建一個deploy.wsdd文件描述服務的名稱、入口等信息:

wsdd文件的顯示有問題下載吧
?

其中service項重的名稱為該服務的名稱即Accountjava:RPC指明了一個JAVA RPC服務,做這個處理的類是org.apache.axis.providers.java.RPCProvider

?? “我們是通過一個標簽告訴RPC服務應該調用的類,而另外一個標簽則告訴引擎,它可以調用這個類中的任何的Public方法。你也可以指定通過使用名字空間或者一些可以調用的方法列表,來指明那些方法可以被調用。”

??? ?當然也可以用Axis提供的一個客戶端管理工具——AdminClient來完成服務的定制發布。這里不說:)

??

然后在DOS下到該目錄下,

java org.apache.axis.client.AdminClient deploy.wsdd

如果出現:

Processing file deploy.wsdd
Doneprocessing

這表明Capacity服務定制發布完成。

好現在你就可以通過http://localhost:8080/axis/services/Account?wsdl來查看WSDL描述了。

?

Web Service發布好了現在調用它吧.

這里說一個最基本的調用需要用的類和方法:

(取出當前的金額)

...

//新建一個服務對象

Service service = new Service();??

//調用服務對象的createCall()方法返回一個命令

Call call = (Call) service.createCall();??

// Sets the address of the target service endpoint.

call.setTargetEndpointAddress(new java.net.URL("http://localhost:8080/axis/services/LxAccount"));

//?Sets the name of the operation to be invoked using this Call instance

call.setOperationName(“getAccount”);

//Convenience method to invoke a //method with a default (empty) namespace

Integer myFund = (Integer) call.invoke(new Object[] {});

...

?

詳細函數可以參考開發API在下載的axis.zip中的docs里面。

下面是詳細的代碼:

編譯后執行就可以。

?

LxClient.java

?

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

?

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encoding.XMLType;

import org.apache.axis.utils.Options;

?

import javax.xml.rpc.ParameterMode;

import javax.xml.namespace.QName;

?

public class LxClient

extends JFrame {

??JTextField jTextField1 = new JTextField();

??JLabel jLabel3 = new JLabel();

??JLabel jLabel1 = new JLabel();

? JButton jButton1 = new JButton();

? JButton jButton2 = new JButton();

??JButton jButton3 = new JButton();

??JLabel jLabel2 = new JLabel();

??JTextField jTextField2 = new JTextField();

?

??public LxClient() {

??? try {

?????? jbInit();

??? }

???? catch (Exception e) {

?????? e.printStackTrace();

???? }

??}

?

??public static void main(String args[]){

?? ?LxClient myframe=new LxClient();

??? myframe.setSize(400,200);

?? ?myframe.setVisible(true);

?

??}

?

?private void jbInit() throws Exception {

?? ?this.getContentPane().setLayout(null);

?? ?jTextField1.setText("");

?? ?jTextField1.setBounds(new Rectangle(131, 51, 80, 24));

?? ?jLabel3.setText("A0317286 李迅");

?? ?jLabel3.setBounds(new Rectangle(102, 15, 108, 17));

??? jLabel1.setText("填入金額:");

??? jLabel1.setBounds(new Rectangle(64, 54, 55, 21));

??? jButton1.setBounds(new Rectangle(50, 96, 58, 23));

??? jButton1.setText("存款");

??? jButton1.addActionListener(new LxClient_jButton1_actionAdapter(this));

??? jButton2.setBounds(new Rectangle(126, 96, 63, 23));

??? jButton2.setText("取款");

??? jButton2.addActionListener(new LxClient_jButton2_actionAdapter(this));

??? jButton3.setBounds(new Rectangle(205, 94, 81, 24));

??? jButton3.setText("查看金額");

??? jButton3.addActionListener(new LxClient_jButton3_actionAdapter(this));

??? jLabel2.setText("當前的金額:");

??? jLabel2.setBounds(new Rectangle(59, 136, 74, 21));

??? jTextField2.setEditable(false);

??? jTextField2.setText("");

??? jTextField2.setBounds(new Rectangle(127, 133, 85, 25));

??? this.getContentPane().add(jTextField1, null);

??? this.getContentPane().add(jLabel3, null);

??? this.getContentPane().add(jLabel1, null);

??? this.getContentPane().add(jButton2, null);

??? this.getContentPane().add(jButton1, null);

??? this.getContentPane().add(jButton3, null);

??? this.getContentPane().add(jLabel2, null);

??? this.getContentPane().add(jTextField2, null);

? ?}

?

?/***************************************************************************

?調用WebService* /

?存款*/

??void jButton1_actionPerformed(ActionEvent e) {

??? try {

??? String endpoint = "http://localhost:8080/axis/services/LxAccount";

??? String method = "deposit";

??? Integer i = Integer.valueOf(jTextField1.getText());

??? Service service = new Service();

??? Call call = (Call) service.createCall();

?

??? call.setTargetEndpointAddress(new java.net.URL(endpoint));

??? call.setOperationName(method);

?

??? Integer myFund = (Integer) call.invoke(new Object[] {i});

??? //更新數據

??? jTextField2.setText(myFund.toString());

??? jLabel1.updateUI();

??? }

??? catch (Exception ex) {

??? System.err.println(ex.toString());

??? }

??}

?/***************************************************************************

? ?取款*/

??void jButton2_actionPerformed(ActionEvent e) {

??? try {

??? String endpoint = "http://localhost:8080/axis/services/LxAccount";

??? String method = "withdraw";

??? Integer i = Integer.valueOf(jTextField1.getText());

????Service service = new Service();

????Call call = (Call) service.createCall();

?

??????? call.setTargetEndpointAddress(new java.net.URL(endpoint));

??????? call.setOperationName(method);

?

??????????? Integer myFund = (Integer) call.invoke(new Object[] {i});

??????? //更新數據

??????? jTextField2.setText(myFund.toString());

??????? jLabel1.updateUI();

?????? }

??????? catch (Exception ex) {

??????? System.err.println(ex.toString());

??? }

??}

??/***************************************************************************

? ?顯示當前金額*/

??void jButton3_actionPerformed(ActionEvent e) {

??? try {

??????? String endpoint = "http://localhost:8080/axis/services/LxAccount";

??????? String method = "getAccount";

?

??????? Service service = new Service();

??????? Call call = (Call) service.createCall();

?

??????? call.setTargetEndpointAddress(new java.net.URL(endpoint));

??????? call.setOperationName(method);

?

??????? Integer myFund = (Integer) call.invoke(new Object[] {});

??????? //更新數據

??????? jTextField2.setText(myFund.toString());

??????? jLabel1.updateUI();

??? }

??? catch (Exception ex) {

??????? System.err.println(ex.toString());

??? }

??}

}

?

class LxClient_jButton1_actionAdapter

??? ?implements java.awt.event.ActionListener {

??LxClient adaptee;

?

??LxClient_jButton1_actionAdapter(LxClient adaptee) {

???? ?this.adaptee = adaptee;

??}

?

??public void actionPerformed(ActionEvent e) {

???? adaptee.jButton1_actionPerformed(e);

??}

}

?

class LxClient_jButton2_actionAdapter

??? ?implements java.awt.event.ActionListener {

?LxClient adaptee;

?

?LxClient_jButton2_actionAdapter(LxClient adaptee) {

??? ?this.adaptee = adaptee;

?}

?

?public void actionPerformed(ActionEvent e) {

??? ?adaptee.jButton2_actionPerformed(e);

??}

}

?

class LxClient_jButton3_actionAdapter

?? ?implements java.awt.event.ActionListener {

?LxClient adaptee;

?

???LxClient_jButton3_actionAdapter(LxClient adaptee) {

??? this.adaptee = adaptee;

??}

?

??public void actionPerformed(ActionEvent e) {

????? adaptee.jButton3_actionPerformed(e);

??}

}

?

?