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

基於 Apache Axis 發布與調用 WebService 完整實戰指南

     編輯:Java 相關知識

Apache Axis 是經典的 Java Web Service 框架,雖然已停止維護,但在大量存量系統中仍廣泛使用。本文詳細記錄基於 Axis 1.4 的 WebService 發布與調用全流程:環境搭建、服務端開發、WSDD 配置、客戶端生成、測試驗證,並解決 .NET 互調兼容性問題。

技術棧與版本

  • Web Service 框架:Apache Axis 1.4
  • Servlet 容器:Apache Tomcat 7+
  • JDK 版本:1.6+
  • 傳輸協議:HTTP + SOAP 1.1

完整部署流程

步驟 1:部署 Axis 到 Tomcat

  1. 下載 Axis 1.4 標準發布包
  2. 將 axis-1.4/webapps/axis 目錄完整複製到 tomcat/webapps/ 下
  3. 啟動 Tomcat,訪問 https://localhost:8080/axis/ 驗證部署成功
  4. 點擊 "Validation" 鏈接檢查必需庫是否齊全

步驟 2:編寫服務端接口與實現

// 接口定義
package org.calculateservice.service;

public interface ICalculate {
    int add(int x, int y);
    int sub(int x, int y);
}

// 實現類
package org.calculateservice.service;

public class CalculateImp implements ICalculate {
    @Override
    public int add(int x, int y) {
        return x + y;
    }
    
    @Override
    public int sub(int x, int y) {
        return x - y;
    }
}

步驟 3:編寫 deploy.wsdd 部署描述文件

放置於 WEB-INF/deploy.wsdd,詳細定義服務元數據:

<deployment xmlns="https://xml.apache.org/axis/wsdd/"
    xmlns:java="https://xml.apache.org/axis/wsdd/providers/java">
    
    <service name="Calculate" provider="java:RPC" use="literal">
        <!-- WSDL 元數據配置 -->
        <parameter name="wsdlTargetNamespace" value="https://web.webservice.CalculateService.org" />
        <parameter name="wsdlServiceElement" value="Calculate" />
        <parameter name="wsdlServicePort" value="CalculateService" />
        <parameter name="wsdlPortType" value="ICalculate" />
        
        <!-- 實現類與作用域 -->
        <parameter name="className" value="org.calculateservice.service.CalculateImp" />
        <parameter name="scope" value="Request" />  <!-- Request/Session/Application -->
        
        <!-- 允許暴露的方法 -->
        <parameter name="allowedMethods" value="add sub" />
        <parameter name="typeMappingVersion" value="1.2" />
        
        <!-- 方法級別詳細定義(可選,Axis 可自動推導) -->
        <operation name="add" qname="operNS:add" 
            xmlns:operNS="https://web.webservice.CalculateService.org"
            returnQName="addReturn" returnType="rtns:int" 
            xmlns:rtns="https://www.w3.org/2001/XMLSchema"
            soapAction="">
            <parameter qname="x" type="tns:int" xmlns:tns="https://www.w3.org/2001/XMLSchema" />
            <parameter qname="y" type="tns:int" xmlns:tns="https://www.w3.org/2001/XMLSchema" />
        </operation>
        
        <operation name="sub" qname="operNS:sub"
            xmlns:operNS="https://web.webservice.CalculateService.org"
            returnQName="subReturn" returnType="rtns:int"
            xmlns:rtns="https://www.w3.org/2001/XMLSchema"
            soapAction="">
            <parameter qname="x" type="tns:int" xmlns:tns="https://www.w3.org/2001/XMLSchema" />
            <parameter qname="y" type="tns:int" xmlns:tns="https://www.w3.org/2001/XMLSchema" />
        </operation>
    </service>
</deployment>

步驟 4:自定義 AxisServlet 解決 .NET 互調問題

Axis 默認要求 SOAPAction Header,.NET 客戶端可能不發送。自定義 Servlet 兼容此場景:

package org.calculateservice.core;

import org.apache.axis.transport.http.AxisServlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

public class AxisServlet extends org.apache.axis.transport.http.AxisServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        // 兼容無 SOAPAction 的請求(.NET 客戶端常見)
        String soapAction = req.getHeader("SOAPAction");
        if (soapAction == null || soapAction.equals("\"\"")) {
            // 從 SOAP Body 推導操作名
            // 實際項目中可根據具體需求實現邏輯
        }
        super.doPost(req, resp);
    }
}

在 web.xml 中替換默認 AxisServlet:

<servlet>
    <servlet-name>AxisServlet</servlet-name>
    <servlet-class>org.calculateservice.core.AxisServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

步驟 5:生成 server-config.wsdd 並發布服務

編寫 generate-server-config.bat:

@echo off
set AXIS_HOME=..\..
set CLASSPATH=%AXIS_HOME%\lib\axis.jar;%AXIS_HOME%\lib\commons-discovery-0.2.jar;
%AXIS_HOME%\lib\commons-logging-1.0.4.jar;%AXIS_HOME%\lib\jaxrpc.jar;
%AXIS_HOME%\lib\saaj.jar;%AXIS_HOME%\lib\log4j-1.2.8.jar;
%AXIS_HOME%\lib\wsdl4j-1.5.1.jar;%CLASSPATH%

java org.apache.axis.utils.AdminServer deploy.wsdd
pause

運行後生成 WEB-INF/server-config.wsdd,服務正式發布。訪問 https://localhost:8080/你的項目/servlet/AxisServlet?wsdl 查看 WSDL。

步驟 6:生成客戶端存根代碼

編寫 wsdl2java.bat:

@echo off
set AXIS_HOME=..\..
set CLASSPATH=%AXIS_HOME%\lib\axis.jar;%AXIS_HOME%\lib\commons-discovery-0.2.jar;
%AXIS_HOME%\lib\commons-logging-1.0.4.jar;%AXIS_HOME%\lib\jaxrpc.jar;
%AXIS_HOME%\lib\saaj.jar;%AXIS_HOME%\lib\log4j-1.2.8.jar;
%AXIS_HOME%\lib\wsdl4j-1.5.1.jar;%CLASSPATH%

java org.apache.axis.wsdl.WSDL2Java -o ./src -p com.client.proxy 
    https://localhost:8080/你的項目/servlet/AxisServlet?wsdl
pause

生成代碼結構:

com.client.proxy/
├── Calculate.java           // Service 接口
├── CalculateService.java    // PortType 接口
├── CalculateServiceLocator.java  // 工廠類(核心調用入口)
├── CalculateSoapBindingStub.java // 具體存根實現
└── deploy.wsdd / undeploy.wsdd  // 客戶端部署描述(可忽略)

步驟 7:客戶端調用測試

package com.client.test;

import com.client.proxy.Calculate;
import com.client.proxy.CalculateServiceLocator;
import javax.xml.rpc.ServiceException;
import java.rmi.RemoteException;

public class TestClient {
    public static void main(String[] args) throws ServiceException, RemoteException {
        // 1. 獲取 Locator 工廠
        Calculate calculate = new CalculateLocator();
        
        // 2. 獲取服務端口(可修改端點地址)
        CalculateService service = calculate.getCalculateService();
        // service._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, "https://新地址/servlet/AxisServlet");
        
        // 3. 調用業務方法
        int result = service.add(1, 2);
        System.out.println("1 + 2 = " + result); // 輸出: 1 + 2 = 3
        
        int result2 = service.sub(5, 3);
        System.out.println("5 - 3 = " + result2); // 輸出: 5 - 3 = 2
    }
}

項目代碼結構

WebContent/
├── WEB-INF/
│   ├── web.xml              // Servlet 配置(含自定義 AxisServlet)
│   ├── deploy.wsdd          // 服務部署描述
│   ├── server-config.wsdd   // 生成的運行時配置
│   └── lib/                 // Axis 依賴 JAR 包
└── src/
    ├── org.calculateservice.service/  // 服務接口與實現
    │   ├── ICalculate.java
    │   └── CalculateImp.java
    ├── org.calculateservice.core/     // 自定義 AxisServlet
    │   └── AxisServlet.java
    └── com.client.proxy/              // WSDL2Java 生成的客戶端代碼
        ├── Calculate.java
        ├── CalculateService.java
        ├── CalculateServiceLocator.java
        └── CalculateSoapBindingStub.java

關鍵問題與解決方案

問題原因解決方案
.NET 客戶端調用失敗.NET 默認不發送 SOAPAction Header自定義 AxisServlet 兼容無 SOAPAction 請求
WSDL 命名空間混亂deploy.wsdd 未顯式指定 targetNamespace在 deploy.wsdd 中完整配置 wsdlTargetNamespace 等參數
客戶端地址硬編碼CalculateLocator 中 endpoint 寫死運行時動態設置:stub._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, newUrl)
複雜類型序列化失敗缺少類型映射註冊在 deploy.wsdd 中添加 <typeMapping> 或使用 JAXB 註解
中文亂碼編碼不一致統一 UTF-8:Tomcat connectorURIEncoding、Axis 配置、SOAP Message 編碼

遷移建議:從 Axis 到現代框架

Axis 1.4 於 2006 年發布,2010 年停止維护,存在安全漏洞、性能差、不支持現代標準(SOAP 1.2、WS-Security、REST)等問題。新項目建議採用:

  • Spring Web Services:契約優先、Spring 生態集成、支持 WS-* 標準
  • Apache CXF:高性能、支持 JAX-WS/JAX-RS、Spring Boot 原生集成
  • JAX-WS RI (Metro):標準參考實現、輕量級
  • REST/JSON (Spring Boot + Jackson):現代首選、輕量、高效、易擴展

本文作為 Axis 存量系統維護的參考文檔,完整記錄了從環境搭建到客戶端調用的全鏈路實踐。理解 Axis 的工作原理,有助於遷移時對接舊系統接口契約。

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