今天因為需要調用第三方的介面些fake service, 用於testcase. 該第三方使用的是soap的webservice模式。
首先是建立service。
package myws;import java.io.IOException;import javax.jws.WebMethod;import javax.jws.WebParam;import javax.jws.WebResult;import javax.jws.WebService;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlRootElement;import javax.xml.ws.Endpoint;/** * * @author 帳前卒 * */@WebService( name="HELLO", targetNamespace="http://chillyc.info/api", serviceName="API", portName="PortName")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("http://localhost:80/fake/ws", new WebServiceHolder()); System.in.read(); }}
這裡寫System.in.read();是希望服務在那裡卡死。基本上所有的server都是類似死迴圈的寫法。所以我這裡就偷懶使用IO.
這裡要注意的是@WebService annotation. 其中 name是指這個portType 叫什麼。 targetNameSpace這個在所有的後續調用中名字都是一致的。serviceName就是服務的名稱。portName 其實就是提供服務的連接埠名稱(這裡對服務本身的調用沒有什麼關係)。如果沒有name, 那麼java會預設使用WebServiceHolder 也就類名稱作為name.
運行後,在瀏覽器中開啟
http://localhost:80/fake/ws?wsdl
然後就可以看到wsdl檔案。
This XML file does not appear to have any style information associated with it. The document tree is shown below.<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --><definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://chillyc.info/api" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://chillyc.info/api" name="API"><types><xsd:schema><xsd:import namespace="http://chillyc.info/api" schemaLocation="http://localhost/fake/ws?xsd=1"/></xsd:schema></types><message name="hello"><part name="parameters" element="tns:hello"/></message><message name="helloResponse"><part name="parameters" element="tns:helloResponse"/></message><message name="getReturnInfo"><part name="parameters" element="tns:getReturnInfo"/></message><message name="getReturnInfoResponse"><part name="parameters" element="tns:getReturnInfoResponse"/></message><portType name="HELLO"><operation name="hello"><input message="tns:hello"/><output message="tns:helloResponse"/></operation><operation name="getReturnInfo"><input message="tns:getReturnInfo"/><output message="tns:getReturnInfoResponse"/></operation></portType><binding name="PortNameBinding" type="tns:HELLO"><soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/><operation name="hello"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation><operation name="getReturnInfo"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation></binding><service name="API"><port name="PortName" binding="tns:PortNameBinding"><soap:address location="http://localhost/fake/ws"/></port></service></definitions>
大家自己對照剛才的那些name, serviceName等,在wsdl檔案中的什麼地方。然後是寫一個stub作為調用的介面。
package myws;import javax.jws.WebParam;import javax.jws.WebService;/** * * @author 帳前卒 * */@WebService(targetNamespace = "http://chillyc.info/api", name="HELLO")public interface WebServiceAPI { String hello(@WebParam(name="name")String name);}
這裡要注意的是 那個hello函數,必須與webService發布的函數名相一致(要看wdsl檔案中的名字。) 另外WebParam中的name也需要和發布函數中的參數名字一致。 這裡WebService中傳入了兩個值。其中name就是剛才WebService中的name. 其實就是wsdl中的portType. 如果這裡寫錯了。就會有Undefined port type:{http://chillyc.info/api}Name. 這個錯誤。所以要小心。另外寫個可執行檔類。
package myws;import java.net.MalformedURLException;import java.net.URL;import javax.xml.namespace.QName;import javax.xml.ws.Service;/** * * @author 帳前卒 * */public class Client { public static void main(String[] args) throws MalformedURLException { WebServiceAPI api = Service.create( new URL("http://localhost:80/fake/ws?wsdl"), new QName("http://chillyc.info/api", "API")) .getPort(WebServiceAPI.class); System.out.println(api.hello("sss")); }}
這裡URL中的就是wsdl檔案的地址。 QName傳入的就是targetNamespace 和 serviceName. 另外getPort就填入剛才的stub. 然後直接調用stub中的介面就能得到結果。done.簡單快速,搭建和寫client 也就是10分鐘搞定。當然這隻是起步
這個方法適用於JDK6及以上,其他版本未知。