Web 服務互操作性源於 WS-I 組織推動的標準化。Java 客戶端可訪問任何遵循規範的 Web 服務(不限 Java 實現)。本文系統介紹 Java 客戶端在 J2SE(非受管)與 J2EE(容器受管)環境下的服務查找與訪問機制,涵蓋 JAX-RPC ServiceFactory、JNDI 查找、靜態存根、動態代理、動態調用接口 (DII) 及動態發現調用 (DDI) 五大核心模式。
核心規範:
兩者均為 J2EE 1.4 組成部分。
標準查找方式,廠商無關,可移植。步驟:
ServiceFactory.newInstance().createService(wsdlURL, serviceQName)。String wsdlURL = "https://localhost:6080/HelloWebService/services/Hello?wsdl";
String namespace = "https://Hello.com";
String serviceName = "HelloWebService";
QName serviceQN = new QName(namespace, serviceName);
ServiceFactory factory = ServiceFactory.newInstance();
Service service = factory.createService(new URL(wsdlURL), serviceQN); // wsdlURL 可選
廠商專屬 ServiceFactory 雖簡化代碼但犧牲可移植性。
JSR 109 強制規定標準方式。客戶端打包為 EAR,含部署描述符聲明服務引用。步驟:
InitialContext。java:comp/env/service/HelloService (建議統一置於 service 子上下文)。Context ic = new InitialContext();
Service service = (Service) ic.lookup("java:comp/env/service/HelloService");
// 或直接轉型為服務專屬介面
HelloServiceInterface svc = (HelloServiceInterface) ic.lookup("java:comp/env/service/HelloService");
容器保證綁定符合 JAX-RPC Service 實現。
獲得 Service 實例後,可獲取三種調用代理:
Java2WSDL、IBM WSDL2Client) 生成 SEI、存根、序列化器等構件。Hello stub = (Hello) service.getHello(); stub.getGreeting("Jane");Service.getPort(portQName, SEI.class) 生成實現 SEI 的代理類。Hello proxy = service.getPort(portQN, Hello.class); proxy.getGreeting("Jane");Service (非受管僅傳服務名 createService(serviceQName),受管 JNDI 查找)。Call call = service.createCall();call.invoke(inputParams) 執行調用。Call call = service.createCall();
call.setPortTypeName(portQN);
call.setOperationName(new QName(namespace, "getGreeting"));
call.setProperty(Call.ENCODINGSTYLE_URI_PROPERTY, "");
call.setProperty(Call.OPERATION_STYLE_PROPERTY, "wrapped");
call.addParameter("param1", XMLType.XSD_STRING, ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);
String ret = (String) call.invoke(new Object[]{"Jane"});
極致靈活:運行時發現 UDDI 服務 → 解析 WSDL 獲取元數據 → DII 調用。步驟:
| 場景 | 推薦模式 |
|---|---|
| 服務穩定、追求簡潔、可接受生成代碼 | 動態代理 |
| 服務頻繁變更、無法預知 WSDL、需極致動態 | DII |
| 舊系統、已有生成工具鏈、性能敏感 | 靜態存根 |
| 需動態發現未知服務 | DDI |
Java Web 服務客戶端開發提供了從靜態到完全動態的完整譜系。理解 JAX-RPC ServiceFactory 與 JNDI 查找的環境區別,掌握存根、動態代理、DII 三種訪問模式的適用邊界,是構建健壯、可移植、可維護服務消費者的關鍵。實際項目中,動態代理往往是平衡開發效率與運行時靈活性的最佳選擇。