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

解決 JAX-WS 「Undefined port type」錯誤:WSDL portType 與 @WebService 映射不一致排查

     編輯:Java 綜合教學

錯誤現象

javax.xml.ws.WebServiceException: Undefined port type: {https://chillyc.info/api}Name

調用 Web Service 客戶端拋出異常,提示找不到對應的 portType 定義。

根本原因

服務端發布的 WSDL 中 `portType` 名稱與客戶端代碼中 `@WebService` 註解的 `name`/`targetNamespace` 不匹配。JAX-WS 運行時通過 `{namespace}localPart` 唯一標識 portType,任何字符差異 (大小寫、拼寫、命名空間) 都會導致此錯誤。

完整代碼對比分析

2.1 服務端接口定義 (SEI)

package myws;

import javax.jws.WebParam;
import javax.jws.WebService;

@WebService(
    targetNamespace = "https://chillyc.info/api",  // 命名空間
    name = "HELLO"                                // portType 名稱 (關鍵!)
)
public interface WebServiceAPI {
    String hello(@WebParam(name = "name") String name);
}

2.2 服務端實現類

package myws;

import javax.jws.*;
import javax.xml.ws.Endpoint;

@WebService(
    name = "HELLO",                           // 必須與接口 name 一致
    targetNamespace = "https://chillyc.info/api",
    serviceName = "API",                      // WSDL service 元素 name
    portName = "PortName"                     // WSDL port 元素 name
)
public class WebServiceHolder {
    @WebMethod
    @WebResult(name = "return")
    public String hello(@WebParam(name = "name") String name) {
        return "hello" + name;
    }

    public static void main(String[] args) throws IOException {
        Endpoint.publish("https://localhost:80/fake/ws", new WebServiceHolder());
        System.in.read();
    }
}

2.3 生成的 WSDL 關鍵片段

<definitions 
    targetNamespace="https://chillyc.info/api" 
    name="API">  <-- service name

  <portType name="HELLO">  <-- 這裡! 對應 @WebService.name
    <operation name="hello">...</operation>
  </portType>

  <binding name="PortNameBinding" type="tns:HELLO">...</binding>

  <service name="API">
    <port name="PortName" binding="tns:PortNameBinding">...</port>
  </service>
</definitions>

2.4 客戶端調用代碼 (錯誤版 vs 正確版)

// ❌ 錯誤:QName 使用了 "API" (service name) 而非 "HELLO" (portType name)
WebServiceAPI api = Service.create(
    new URL("https://localhost:80/fake/ws?wsdl"),
    new QName("https://chillyc.info/api", "API")  // 錯誤! 應為 portType 名稱
).getPort(WebServiceAPI.class);

// ✅ 正確:使用 portType 名稱 "HELLO"
WebServiceAPI api = Service.create(
    new URL("https://localhost:80/fake/ws?wsdl"),
    new QName("https://chillyc.info/api", "HELLO")  // 匹配 WSDL portType name
).getPort(WebServiceAPI.class);

核心映射關係表

註解屬性WSDL 元素客戶端 QName 參考常見錯誤
@WebService.name<portType name="...">Service.create(wsdlUrl, QName(ns, portType名))寫成 serviceName 或 portName
@WebService.targetNamespacedefinitions/@targetNamespaceQName 的 namespace 參數命名空間不一致 (大小寫/尾斜杠)
@WebService.serviceName<service name="...">通常不直接用於 getPort誤作為 portType 名稱
@WebService.portName<port name="...">獲取特定端口時使用誤作為 portType 名稱
@WebParam.name<part name="...">參數映射與 WSDL message part 不一致

排查檢查清單

🔍 逐項核對

  1. 服務端接口 `@WebService.name` = "HELLO"
  2. 服務端實現類 `@WebService.name` = "HELLO" (必須一致)
  3. 服務端 `@WebService.targetNamespace` = "https://chillyc.info/api" (兩處一致)
  4. 客戶端 new QName("https://chillyc.info/api", "HELLO") 完全匹配上述兩值
  5. 參數註解 `@WebParam(name="name")` 與 WSDL message part 名稱一致
  6. 重新發布服務後,瀏覽器訪問 ?wsdl 確認 WSDL 內容已更新

進階:從 WSDL 生成客戶端代碼 (避免手寫錯誤)

# 使用 wsimport 生成客戶端存根 (JDK 自帶)
wsimport -keep -p com.example.client https://localhost:80/fake/ws?wsdl

# 生成的代碼中會包含正確的 QName 常量
// com.example.client.WebServiceAPI_Service.java
public class WebServiceAPI_Service extends Service {
    private final static QName WEBSERVICEAPI_QNAME = 
        new QName("https://chillyc.info/api", "HELLO"); // 自動提取正確 portType
    ...
}

總結

「Undefined port type」本質是 WSDL 契約與客戶端代碼的命名不一致。核心對應關係:@WebService.name → WSDL portType name → 客戶端 QName localPart。建議採用「WSDL 先行」或「wsimport 生成客戶端」模式,從源頭消除手寫映射錯誤。調試時直接查看 ?wsdl 確認 portType 名稱是最高效定位手段。

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