首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Axis 開發 Web Service 完整實戰教學:從安裝到部署

     編輯:Java 相關知識

前言

Apache Axis 是早期 Java 平台上最主流的 Web Service 實作框架,雖然現已逐漸被 JAX-WS 等標準取代,但在維護舊系統或理解 SOAP 架構演進時仍具參考價值。本文詳細記錄 Axis 安裝、三種開發模式(DII、Stubs、Dynamic Proxy)與 WSDD 部署的完整實作流程。

一、環境準備與 Axis 安裝

所需軟體版本

  • J2SE SDK 1.4.2
  • Tomcat 5.0

安裝步驟

  1. 至 Axis 官網 下載最新發布包。
  2. 解壓縮,將 webapps/axis 目錄複製至 TOMCAT_HOME/webapps/。
  3. 啟動 Tomcat,瀏覽器開啟 https://localhost:8080/axis 確認安裝成功(應出現 Axis 服務列表頁)。

二、Axis 三種開發模式概覽

模式核心特性優點缺點
DII (Dynamic Invocation Interface) 執行期動態構建 Call 物件呼叫 無需預先產生 Stub,適合動態發現服務 程式碼冗長、型別安全性低、維護困難
Stubs 方式 由 WSDL 產生強型別客戶端類別 IDE 自動完成支援好、編譯期檢查、團隊協作友善 需額外建置步驟、WSDL 變更需重新產生
Dynamic Proxy 基於介面的動態代理,JSR-109 風格 程式碼簡潔、面向介面設計、解耦合度高 需理解 Proxy 機制、除錯相對困難

三、DII 模式完整實作

1. 服務端:HelloClient.jws

public class HelloClient {
    public String getName(String name) {
        return "hello " + name;
    }
}

將檔案放入 AXIS_HOME 並命名為 HelloClient.jws,Axis 自動發布。

2. 客戶端:TestHelloClient.java

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import java.net.MalformedURLException;
import java.rmi.RemoteException;

public class TestHelloClient {
    public static void main(String[] args) {
        try {
            String endpoint = "https://localhost:8080/axis/HelloClient.jws";
            Service service = new Service();
            Call call = (Call) service.createCall();
            call.setOperationName(new QName("https://localhost:8080/axis/HelloClient.jws", "getName"));
            call.setTargetEndpointAddress(new java.net.URL(endpoint));
            String ret = (String) call.invoke(new Object[] {"張三"});
            System.out.println("return value is " + ret);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

四、Dynamic Proxy 模式實作

1. 定義遠端介面

public interface HelloClientInterface extends java.rmi.Remote {
    public String getName(String name) throws java.rmi.RemoteException;
}

2. 客戶端程式碼

import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import java.net.URL;
import javax.xml.namespace.QName;

public class TestHelloClient {
    public static void main(String[] args) {
        try {
            String wsdlUrl = "https://localhost:8080/axis/HelloClient.jws?wsdl";
            String namespaceUri = "https://localhost:8080/axis/HelloClient.jws";
            String serviceName = "HelloClientService";
            String portName = "HelloClient";

            ServiceFactory factory = ServiceFactory.newInstance();
            Service service = factory.createService(new URL(wsdlUrl), new QName(namespaceUri, serviceName));
            HelloClientInterface proxy = (HelloClientInterface) service.getPort(new QName(namespaceUri, portName), HelloClientInterface.class);

            System.out.println("return value is " + proxy.getName("John"));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

五、WSDD 部署 + Stub 客戶端(企業級標準流程)

1. 服務實作類別

package server;
public class SayHello {
    public String getName(String name) {
        return "hello " + name;
    }
}

2. 自訂 LogHandler

import org.apache.axis.AxisFault;
import org.apache.axis.Handler;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;
import java.util.Date;

public class LogHandler extends BasicHandler {
    public void invoke(MessageContext msgContext) throws AxisFault {
        try {
            Handler serviceHandler = msgContext.getService();
            Integer numAccesses = (Integer) serviceHandler.getOption("accesses");
            if (numAccesses == null) numAccesses = new Integer(0);
            numAccesses = new Integer(numAccesses.intValue() + 1);
            Date date = new Date();
            String result = date + ": service " + msgContext.getTargetService() + " accessed " + numAccesses + " time(s).";
            serviceHandler.setOption("accesses", numAccesses);
            System.out.println(result);
        } catch (Exception e) {
            throw AxisFault.makeFault(e);
        }
    }
}

3. deploy.wsdd 部署描述檔

<deployment xmlns="https://xml.apache.org/axis/wsdd/"
    xmlns:java="https://xml.apache.org/axis/wsdd/providers/java">
    <handler name="print" type="java:LogHandler"/>
    <service name="sayhello" provider="java:RPC">
        <requestFlow><handler type="print"/></requestFlow>
        <parameter name="className" value="server.SayHello"/>
        <parameter name="allowedMethods" value="*"/>
    </service>
</deployment>

4. 部署指令

# 複製編譯後的 class 到 AXIS_HOME/WEB-INF/classes
java org.apache.axis.client.AdminClient deploy.wsdd

5. 產生 Stub 兩種方式

方式一:從 .jws 產生

java org.apache.axis.wsdl.WSDL2Java -p client https://localhost:8080/axis/services/SayHello.jws?wsdl

方式二:從 Java 類別產生 WSDL 再產生 Stub

java org.apache.axis.wsdl.Java2WSDL -o SayHello.wsdl -l https://localhost:8080/axis/services/SayHello -n sayhello server.SayHello
java org.apache.axis.wsdl.WSDL2Java SayHello.wsdl -p client

6. 客戶端呼叫

public class SayHelloClient {
    public static void main(String[] args) {
        try {
            SayHelloService service = new client.SayHelloServiceLocator();
            client.SayHello_PortType client = service.getSayHello();
            String retValue = client.getName("張三");
            System.out.println(retValue);
        } catch (Exception e) {
            System.err.println("Execution failed. Exception: " + e);
        }
    }
}

六、常見問題與除錯技巧

  • ClassNotFoundException:確認 axis.jar、jaxrpc.jar、saaj.jar、commons-logging.jar、commons-discovery.jar、wsdl4j.jar 皆在 Classpath 中。
  • 連線被拒絕:檢查 Tomcat 是否啟動、Port 8080 是否被佔用、防火牆設定。
  • WSDL 無法存取:確認服務名稱拼寫正確、deploy.wsdd 中 service name 與 URL 路徑一致。
  • Stub 產生失敗:嘗試加上 -v 參數查看詳細錯誤訊息,或手動下載 WSDL 檔案離線產生。

結語

Axis 雖屬上一代技術,但其 DII、Stub、Dynamic Proxy 三種呼叫模式完整展示了 SOAP Web Service 的演進脈絡。理解這些基礎有助於維護舊系統、排查相容性問題,也能更深刻體會現代 JAX-WS / Spring WS 框架的設計哲學。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved