跨語言 WebService 對接是企業級集成常態。本文完整演示 Java Axis 1.4 服務端 暴露返回自定義對象 Person 的 login 方法,PHP 5.2+ NuSOAP 客戶端 調用並處理複雜類型返回的全流程代碼。
package com.example.ws;
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = -410186774891162281L;
private String username;
private int age;
private boolean sex; // true: male, false: female
// Getter/Setter 略
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public boolean isSex() { return sex; }
public void setSex(boolean sex) { this.sex = sex; }
}
package com.example.ws;
public class UserLogin {
public Person login(String loginName, String loginPasswd) {
Person p = new Person();
if ("laoli".equals(loginName) && "111111".equals(loginPasswd)) {
p.setUsername("老李");
p.setAge(55);
p.setSex(true);
} elseif ("xiaoli".equals(loginName) && "123456".equals(loginPasswd)) {
p.setUsername("小麗");
p.setAge(23);
p.setSex(false);
} else {
return null;
}
return p;
}
}
<deployment xmlns="https://xml.apache.org/axis/wsdd/"
xmlns:java="https://xml.apache.org/axis/wsdd/providers/java">
<service name="UserLoginWS" provider="java:RPC">
<parameter name="className" value="com.example.ws.UserLogin"/>
<parameter name="allowedMethods" value="login"/>
<!-- 複雜類型映射 -->
<typeMapping
xmlns:ns="https://ws.example.com"
qname="ns:Person"
type="java:com.example.ws.Person"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle="https://schemas.xmlsoap.org/soap/encoding/"/>
</service>
</deployment>
<?php
header("Content-Type: text/html;charset=utf-8");
require_once("libs/nusoap.php"); // NuSOAP 庫
$wsdl = 'https://localhost:8080/axis/services/UserLoginWS?wsdl';
$client = new nusoap_client($wsdl, true); // true = WSDL 模式
$client->soap_defencoding = 'utf-8';
$client->decode_utf8 = false;
$client->xml_encoding = 'utf-8';
// 錯誤檢查
if ($err = $client->getError()) {
die("Constructor error
$err
");
}
// 調用 login
$params = ['loginName' => 'laoli', 'loginPasswd' => '111111'];
$result = $client->call('login', $params);
// 統一異常處理
if ($client->fault) {
echo "Fault
"; print_r($result); echo "
";
} else {
$err = $client->getError();
if ($err) {
echo "Error
$err
";
} else {
echo "Result
"; print_r($result); echo "
";
}
}
// 第二次調用
$params = ['loginName' => 'xiaoli', 'loginPasswd' => '123456'];
$result = $client->call('login', $params);
// 同樣錯誤處理...
| NuSOAP 選項 | 作用 | 建議值 |
|---|---|---|
| soap_defencoding | 發送請求 XML 編碼 | 'utf-8' |
| decode_utf8 | 是否自動 UTF-8 解碼響應 | false (手動控制) |
| xml_encoding | 生成 XML 聲明編碼 | 'utf-8' |
| call() 參數結構 | 關聯陣列鍵需與 WSDL message part 名一致 | ['loginName'=>..., 'loginPasswd'=>...] |
NuSOAP 將複雜類型解析為巢狀關聯陣列:
Array
(
[return] => Array
(
[username] => 老李
[age] => 55
[sex] => 1 // boolean true → 1
)
)
訪問方式:$result['return']['username']。
| 問題 | 原因 | 解決 |
|---|---|---|
| Class 'nusoap_client' not found | NuSOAP 庫未引入 | 下載 nusoap.php 放入 libs/,require_once |
| SOAP-ERROR: Parsing WSDL | WSDL 無法訪問/編碼錯誤 | 瀏覽器驗證 ?wsdl、檢查防火牆、編碼統一 UTF-8 |
| 返回 null / 空對象 | Java 端邏輯未匹配、類型映射缺失 | 檢查 deploy.wsdd typeMapping、Java 邏輯日誌 |
| 中文亂碼 | 編碼不一致 | 全鏈路 UTF-8,NuSOAP 設定上述三項編碼參數 |
| Axis 1.4 序列化差異 | Axis 對 null、空陣列序列化行為特殊 | Java 端避免返回 null,改拋異常或返回空對象標記 |
ext/soap (原生 SoapClient) 替代 NuSOAP,性能更好、無第三方依賴。掌握 WSDL 複雜類型映射、NuSOAP 編碼控制、異常處理流程,即可駕馭 PHP-Java SOAP 集成的核心難點。