ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Apache Axis1.4 官网备份与老系统维护实战指南

Apache Axis1.4 官网备份与老系统维护实战指南

简介:Apache Axis1.4 官网备份是一份面向 Java Web 服务开发者与教学研究者的历史版本资源包,用于在官方停止维护后仍能搭建 SOAP 服务端与客户端环境,适合需要复现早期 JAX-RPC、WSDL 自动代码生成及 SOAP 1.1/1.2 通信场景的中高级开发者。压缩包共 187 个文件,约 3.07MB,以 161 个 class 字节码、12 个 jar 依赖库为主,辅以 4 个 jsp 页面、3 个 jws 服务脚本及 properties、xml、java 等配置与源码文件,覆盖 Axis 运行所需的核心组件与示例。内容涉及 SOAP 消息处理、WSDL 描述、服务部署与互操作测试等模块,可帮助读者理解 Axis1.4 的部署结构与调用链路,为迁移到 CXF、Spring Web Services 等现代框架提供对照参考。目前已有 215 人学习下载,适合作为 Web 服务技术演进研究的存档资料。

1. Apache Axis1.4 官网备份:当老系统还在跑,你需要的不是新轮子

接手一套还在用 Apache Axis1.4 的老系统,第一反应往往是“这玩意儿还有人用?”——但现实是,不少政务、金融、制造业的内部系统,SOAP 接口至今跑在 Axis1.4 上,稳定运行十几年,没人敢动。问题在于,官网早已归档,文档散落,jar 包下载链接失效,新人接手时连个完整的参考都找不到。所谓“官网备份”,本质是把 Axis1.4 的运行时、文档、依赖和典型配置完整地留存下来,让老系统能继续维护、迁移或对接。这件事适合两类人:一是被迫维护遗留 SOAP 服务的后端工程师,二是需要把老接口接入新中台或网关的集成开发者。别指望官方再更新,你要做的是自己建一份可复现的本地知识库和依赖仓库。

2. 先搞清楚 Axis1.4 的运行时到底由哪些东西组成

2.1 核心 jar 包与依赖树:别只盯着 axis.jar

Axis1.4 的发布包看似简单,实际运行时依赖不少。最核心的是axis.jar,但它不能单独工作。常见的最小运行时集合包括:

  • axis.jar:SOAP 引擎主体,负责 WSDL 解析、消息序列化、Handler 链
  • jaxrpc.jar:JAX-RPC 1.1 API,Axis1.4 实现了这套规范
  • saaj.jar:SOAP with Attachments API,处理带附件的消息
  • commons-discovery-0.2.jar:服务发现,Axis 用来查找 Handler
  • commons-logging-1.0.4.jar:日志门面,Axis 内部大量使用
  • wsdl4j-1.5.1.jar:WSDL 解析,没有它启动直接报 ClassNotFound
  • activation.jar、mail.jar:如果用到附件或 MIME 类型,这两个必须加

很多新手只复制axis.jar,结果一启动就报NoClassDefFoundError,然后开始到处搜 jar,浪费半天。我一般会直接建一个lib目录,把上述 jar 全部放进去,再用java -cp "lib/*"的方式启动,避免逐个指定。

提示:Axis1.4 对 JDK 版本敏感,官方支持 JDK 1.4/1.5,实际在 JDK 8 上跑通常没问题,但 JDK 11 以上会因javax.xml.rpc等包被移除而报错。如果必须用高版本 JDK,需要额外引入javax.xml.rpc-api等替代包,或者干脆用 Docker 跑一个 JDK 8 环境。

2.2 官网备份到底要备份什么:目录结构比 jar 更重要

“官网备份”不是把 axis.apache.org 整个爬下来,而是把对维护有用的部分结构化留存。我通常按以下目录组织:

axis1.4-backup/ ├── lib/ # 所有运行时 jar ├── docs/ # 官方文档离线版 │ ├── user-guide.html │ ├── reference.html │ └── api/ # javadoc ├── samples/ # 官方示例代码 │ ├── stock/ # 股票查询示例 │ └── addressbook/ # 通讯录示例 ├── tools/ # 命令行工具 │ ├── wsdl2java.sh │ └── java2wsdl.sh ├── conf/ # 典型配置模板 │ ├── server-config.wsdd │ └── client-config.wsdd └── README.md # 记录版本、来源、已知问题

这个结构的好处是:新人拿到后,不用翻官网就能跑通示例、生成客户端、部署服务。docs目录建议用wget做镜像,但注意去掉外部追踪脚本,只保留静态 HTML 和 API 文档。

2.3 用 wsdl2java 生成客户端:最小可运行命令

Axis1.4 自带的wsdl2java是最高频的工具。假设你有一个hello.wsdl,想生成客户端存根:

# 设置 AXIS_HOME 指向备份目录 export AXIS_HOME=/opt/axis1.4-backup export CLASSPATH=$AXIS_HOME/lib/axis.jar:$AXIS_HOME/lib/jaxrpc.jar:$AXIS_HOME/lib/wsdl4j-1.5.1.jar:$AXIS_HOME/lib/commons-discovery-0.2.jar:$AXIS_HOME/lib/commons-logging-1.0.4.jar # 生成客户端代码到 src/client 目录 java -cp "$CLASSPATH" org.apache.axis.wsdl.WSDL2Java \ -o src/client \ -p com.example.hello \ hello.wsdl

参数说明:

  • -o:输出目录,生成的文件按包名放子目录
  • -p:指定包名,不指定会按 WSDL 的 targetNamespace 自动生成,往往很丑
  • hello.wsdl:可以是本地文件,也可以是 URL,但生产环境建议先下载到本地再生成,避免网络波动

生成后你会得到HelloService.java、HelloServiceLocator.java、HelloPortType.java等。调用时用 Locator 获取端口,再调方法。注意:Axis1.4 生成的存根默认走http,如果服务端是https,需要额外配置AxisProperties或自定义SocketFactory,否则会报 SSL 握手失败。

3. 把 Axis1.4 服务跑起来:从 WSDD 配置到 Servlet 部署

3.1 server-config.wsdd 的四个关键段落

Axis1.4 的服务端配置全靠server-config.wsdd。一个能跑的最小配置包含四部分:

<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <!-- 1. 全局配置:指定 Handler 和日志 --> <globalConfiguration> <parameter name="sendStacktraceDetails" value="true"/> <parameter name="disablePrettyXML" value="false"/> </globalConfiguration> <!-- 2. 传输层:HTTP 监听器 --> <transport name="http"> <parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler"/> </transport> <!-- 3. 服务定义:把 Java 类暴露为 SOAP 服务 --> <service name="HelloService" provider="java:RPC"> <parameter name="className" value="com.example.hello.HelloServiceImpl"/> <parameter name="allowedMethods" value="sayHello"/> <parameter name="scope" value="Request"/> </service> <!-- 4. 类型映射:自定义对象序列化 --> <beanMapping qname="ns1:User" xmlns:ns1="http://example.com/types" languageSpecificType="java:com.example.hello.User"/> </deployment>

逻辑说明:

  • globalConfiguration里的sendStacktraceDetails在调试时设为true,生产环境务必改false,否则异常堆栈会直接返回给客户端,泄露内部路径
  • transport定义 HTTP 传输,Axis1.4 默认用AxisServlet处理/services/*
  • service的provider="java:RPC"表示用 RPC 方式调用 Java 方法,allowedMethods用逗号分隔,不写则暴露所有 public 方法,有安全风险
  • beanMapping用于自定义类型,如果服务返回User对象,不加这段会报No serializer found

3.2 在 Tomcat 中部署 Axis1.4 的完整步骤

把 Axis1.4 部署到 Tomcat 是常见做法,步骤不复杂但容易漏:

  1. 在 Tomcat 的webapps下新建axis目录
  2. 把axis.jar、jaxrpc.jar、saaj.jar、wsdl4j-1.5.1.jar、commons-discovery-0.2.jar、commons-logging-1.0.4.jar复制到axis/WEB-INF/lib/
  3. 从备份的samples里找到web.xml,复制到axis/WEB-INF/,内容如下:
<web-app> <servlet> <servlet-name>AxisServlet</servlet-name> <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> </web-app>
  1. 把server-config.wsdd放到axis/WEB-INF/下
  2. 启动 Tomcat,访问http://localhost:8080/axis/services,能看到服务列表就成功了

注意:如果访问/services报 404,先检查web.xml的url-pattern是否写成了/services而不是/services/*。少了/*会导致只有精确路径能匹配,列表页打不开。

3.3 用 TCPMonitor 抓 SOAP 报文:调试必备

Axis1.4 自带tcpmon工具,可以监听本地端口,把请求转发到真实服务,同时打印完整 SOAP 报文。启动方式:

java -cp "$CLASSPATH" org.apache.axis.utils.tcpmon 8081 localhost 8080

含义:监听本地 8081,转发到 localhost:8080。然后把客户端的目标地址改成http://localhost:8081/axis/services/HelloService,就能在 tcpmon 窗口看到请求和响应的 XML。这个工具在排查“客户端报错但服务端日志没记录”时特别有用——往往是 SOAPAction 头不对,或者命名空间不匹配,报文里一眼就能看出来。

4. 避坑:Axis1.4 维护中最容易翻车的五个场景

4.1 现象:客户端报 “No SOAPAction header” → 原因:HTTP 头缺失 → 解决:显式设置 SOAPAction

Axis1.4 的客户端在某些容器或代理后面运行时,可能丢失SOAPAction头。服务端如果配置了use="literal"且要求 SOAPAction,就会拒绝。解决办法是在调用前设置:

((org.apache.axis.client.Stub) port)._setProperty( org.apache.axis.client.Call.SOAPACTION_USE_PROPERTY, Boolean.TRUE); ((org.apache.axis.client.Stub) port)._setProperty( org.apache.axis.client.Call.SOAPACTION_URI_PROPERTY, "urn:sayHello");

SOAPACTION_URI_PROPERTY的值要和 WSDL 里soap:operation的soapAction一致,不能随便写。

4.2 现象:中文乱码 → 原因:Axis1.4 默认用 ISO-8859-1 编码 → 解决:改 charset 或加过滤器

Axis1.4 的AxisServlet默认按 ISO-8859-1 解析请求体,中文会变问号。常见做法是在server-config.wsdd的globalConfiguration里加:

<parameter name="axis.encoding" value="UTF-8"/>

如果不起作用,就在web.xml里加一个CharacterEncodingFilter,强制request.setCharacterEncoding("UTF-8")。注意:过滤器要放在AxisServlet之前,且url-pattern覆盖/services/*。

4.3 现象:WSDL 里出现localhost→ 原因:Axis 自动生成时用了请求的 Host → 解决:固定axis.url参数

当 Axis1.4 部署在反向代理后面,生成的 WSDL 里soap:address可能是内网 IP 或 localhost,外部客户端无法访问。在server-config.wsdd的globalConfiguration里加:

<parameter name="axis.url" value="http://your-public-domain/axis/services"/>

这样 WSDL 里的地址就会固定成你指定的值。如果用了 HTTPS,还要确保axis.url以https开头,否则客户端会按 HTTP 连接。

4.4 现象:大附件传输内存溢出 → 原因:Axis1.4 默认把附件读进内存 → 解决:启用流式处理

Axis1.4 处理MIME附件时,默认用ByteArrayInputStream全量加载。如果附件几十 MB,很容易 OOM。可以在server-config.wsdd里配置:

<parameter name="attachment.directory" value="/tmp/axis-attachments"/> <parameter name="attachment.threshold" value="1048576"/>

attachment.threshold设为 1MB,超过这个大小的附件会写到磁盘临时目录,而不是全放内存。注意临时目录要有写权限,且定期清理,否则磁盘会被占满。

4.5 现象:JDK 升级后启动报javax.xml.rpc不存在 → 原因:JDK 11 移除了 Java EE 模块 → 解决:手动引入替代包

JDK 11 开始,javax.xml.rpc、javax.xml.soap等包不再内置。如果必须用高版本 JDK,需要引入jakarta.xml.rpc-api和jakarta.xml.soap-api,但 Axis1.4 内部引用的类名还是javax.*,会出现兼容问题。最稳妥的做法是用 Docker 跑 JDK 8:

FROM openjdk:8-jre-slim COPY axis1.4-backup /opt/axis1.4-backup COPY tomcat /opt/tomcat EXPOSE 8080 CMD ["/opt/tomcat/bin/catalina.sh", "run"]

这样既保留了老环境,又隔离了依赖,不会影响宿主机上的其他服务。

5. 进阶:把 Axis1.4 备份变成可检索的本地知识库

5.1 用 javadoc 和 WSDL 建立离线索引

备份的docs/api目录是纯 HTML,搜索不方便。我一般用grep加ripgrep做快速检索:

# 在所有 javadoc 里搜某个类的方法 rg -i "class Call" /opt/axis1.4-backup/docs/api/ --type html -l # 在 WSDL 示例里搜特定命名空间 rg "urn:example" /opt/axis1.4-backup/samples/ -g "*.wsdl"

如果想把 javadoc 转成可搜索的文本,可以用pandoc批量转换:

find /opt/axis1.4-backup/docs/api -name "*.html" -exec pandoc -f html -t plain {} \; > axis-api.txt

这样就能用less或编辑器直接搜关键词,比翻 HTML 快得多。

5.2 用 Docker Compose 一键拉起 Axis1.4 测试环境

为了快速验证老接口,我习惯写一个docker-compose.yml:

version: '3' services: axis: build: . ports: - "8080:8080" volumes: - ./axis1.4-backup:/opt/axis1.4-backup - ./logs:/opt/tomcat/logs environment: - JAVA_OPTS=-Xmx512m -Daxis.url=http://localhost:8080/axis/services

配合前面的 Dockerfile,docker-compose up就能在本地跑起一个完整的 Axis1.4 服务。改server-config.wsdd后重启容器即可,不用污染宿主机环境。这个习惯帮我省了很多“在我机器上能跑”的扯皮时间。

5.3 一个具体技巧:用java2wsdl反向生成 WSDL 并比对差异

老系统迁移时,经常需要确认服务端实际暴露的 WSDL 和文档是否一致。Axis1.4 自带java2wsdl,可以从 Java 类反向生成 WSDL:

java -cp "$CLASSPATH" org.apache.axis.wsdl.Java2WSDL \ -o generated.wsdl \ -l "http://localhost:8080/axis/services/HelloService" \ -n "urn:HelloService" \ -p "com.example.hello" \ com.example.hello.HelloServiceImpl

然后把generated.wsdl和线上/services/HelloService?wsdl下载的 WSDL 做 diff。如果差异只在soap:address,说明服务实现和文档一致;如果方法签名或类型定义有差异,说明有人改了代码没更新文档,这时候就要以实际 WSDL 为准去调整客户端。这个比对动作在对接第三方系统时特别关键,能避免“按文档写客户端却调不通”的尴尬。

我自己的习惯是:每次接手 Axis1.4 老系统,先花半小时把官网备份目录建好,把 jar、文档、示例、配置模板全部归档,再用 Docker 跑一个最小服务验证。后面无论排查问题还是迁移接口,都有据可查,不用再满互联网找失效的下载链接。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进