Java Web Service的客戶端實現(xiàn)有三種
1. 生成的stub
2. 動態(tài)代理
3. 動態(tài)調用接口
其中生成stub是最常用的。stub是用JAX-RPC編譯器根據(jù)WSDL文檔生成的,其主要功能是將對endpoint接口的方法調用轉化為SOAP 消息,并且負責將返回的SOAP響應轉換為方法的返回值,把SOAP fault轉化為方法的異常。JAX-RPC編譯器產生的stub除了要實現(xiàn)endpoint接口外,還需要實現(xiàn)或繼承 javax.xml.rpc.Stub接口或其實現(xiàn)的子類(Axis中是org.apache.axis.client.Stub)。 javax.xml.rpc.Stub接口主要定義了和網絡通訊和認證相關的屬性的設置和獲取的機制。
Java Web Service的客戶端實現(xiàn)有三種
1. 生成的stub
2. 動態(tài)代理
3. 動態(tài)調用接口
其中生成stub是最常用的。stub是用JAX-RPC編譯器根據(jù)WSDL文檔生成的,其主要功能是將對endpoint接口的方法調用轉化為SOAP 消息,并且負責將返回的SOAP響應轉換為方法的返回值,把SOAP fault轉化為方法的異常。JAX-RPC編譯器產生的stub除了要實現(xiàn)endpoint接口外,還需要實現(xiàn)或繼承 javax.xml.rpc.Stub接口或其實現(xiàn)的子類(Axis中是org.apache.axis.client.Stub)。 javax.xml.rpc.Stub接口主要定義了和網絡通訊和認證相關的屬性的設置和獲取的機制。其代碼如下:
package javax.xml.rpc;
import java.util.Iterator;
public interface Stub {
// Standard property: The Web service‘s Internet address.
public static String ENDPOINT_ADDRESS_PROPERTY;
// Standard property: Password for authentication.
public static String PASSWORD_PROPERTY;
// Standard property: User name for authentication.
public static String USERNAME_PROPERTY;
// Standard property: Boolean flag for maintaining an HTTP session.
public static String SESSION_MAINTAIN_PROPERTY;
// Given a property name, get its value.
public Object _getProperty(java.lang.String name);
// Get the names of all the properties the stub supports.
public Iterator _getPropertyNames();
// Configure a property on the stub.
public void _setProperty(java.lang.String name, java.lang.Object value);
}
JAX-RPC編譯器產生還可以產生一個和WSDL中service元素對應的Service接口,該接口組合了多個port,也就是多個Stub。該接口繼承了javax.xml.rpc.Service。在J2EE環(huán)境中Service接口通常通過JNDI lookup得到。
在J2EE中使用生成的stub的典型用例如下:
代碼:
package com.jwsbook.jaxrpc;
import javax.servlet.http.*;
import javax.servlet.*;
import javax.naming.InitialContext;
public class BookQuoteServlet_1 extends javax.servlet.http.HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException,java.io.IOException {
try{
String isbn = req.getParameter("isbn");
InitialContext jndiContext = new InitialContext();
BookQuoteService service = (BookQuoteService)
jndiContext.lookup("java:comp/env/service/BookQuoteService");
BookQuote bookQuote = service.getBookQuotePort();
float price = bookQuote.getBookPrice( isbn );
java.io.Writer outStream = resp.getWriter();
outStream.write("The wholesale price for ISBN:"+isbn+
" = "+price+"");
}catch(javax.naming.NamingException ne){
throw new ServletException(ne);
}catch(javax.xml.rpc.ServiceException se){
throw new ServletException(se);
}
}
部署說明文件:
service/BookQuoteService
com.jwsbook.jaxrpc.BookQuoteService
BookQuote.wsdl
mh:BookQuoteService
一般都是通過JNDI查詢到相應的Service接口,然后從Service接口中得到stub,最后調用web service的方法。部署文件中申明了名為"service/BookQuoteService"的Service接口,在代碼里獲取該接口的代碼是 jndiContext.lookup("java:comp/env/service/BookQuoteService"),前綴"java: comp/env/"是所有J2EE資源在JNDI樹種的parent Context。
在非J2EE環(huán)境中實現(xiàn)web service客戶端
在非J2EE環(huán)境中也可以實現(xiàn)web service客戶端,這時需要用到javax.xml.rpc.ServiceFactory(或其子類,在axis中是 org.apache.axis.client.ServiceFactory)的靜態(tài)方法loadService得到service接口。接下來的調用代碼和J2EE中的類似。
動態(tài)代理調用
動態(tài)代理調用是Java web service的另一種方式。對于使用該方式的客戶端代碼,和生成stub的方式相比較,其變化不是很大。它和生成stub的方式主要區(qū)別在于前者在編譯時刻產生service接口和stub,后者則將這部分工作延遲到運行時刻。
動態(tài)代理調用的典型代碼和部署說明文件:
package com.jwsbook.jaxrpc;
import javax.naming.InitialContext;
public class JaxRpcExample_2 {
public static void main(String [] args) throws Exception{
String isbn = args[0];
InitialContext jndiContext = new InitialContext();
javax.xml.rpc.Service service = (javax.xml.rpc.Service)
jndiContext.lookup("java:comp/env/service/Service");
BookQuote BookQuote_proxy = (BookQuote)
service.getPort(BookQuote.class);
float price = BookQuote_proxy.getBookPrice( isbn );
System.out.println("The price is = "+price);
}
}
service/Service
javax.xml.rpc.Service
BookQuote.wsdl
mh:BookQuoteService
由于不需要在編譯時刻產生service接口和stub,用JNDI lookup和部署說明時只使用了javax.xml.rpc.Service。得到service接口后通過getPort方法可以取得動態(tài)代理的 stub。getPort有兩種版本,getPort(java.lang.Class endpointInterface)和getPort(javax.xml.namespace.QName portName,java.lang.Class endpointInterface),通常當WSDL中一個PortType有一種以上的綁定時,如果需要得到某個綁定的port接口就使用后者,否者使用前者。QName是該綁定的完全限定名稱,有命名空間加上局部名構成。對應的QName對象的構造方法有構造函數(shù)法和靜態(tài)valueOf法,實例如下:
// Use constructor method
QName portName =
new QName("http://www.Monson-Haefel/jwsbook/BookQuote",
"BookQuoteLiteralPort");
// Use static valueOf() method
String s = "{http://www.Monson-Haefel/jwsbook/BookQuote}BookQuoteLiteralPort";
QName qname2 = QName.valueOf(s);
valueOf方法接受的String參數(shù)以"{namespace}localName"的模式構成。
PortType有一種以上的綁定時還需要在JAX-RPC Mapping 文件中說明不指定QName版本的getPort方法對應的port綁定。示例:
<?xml version=‘1.0‘ encoding=‘UTF-8‘ ?>
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:mh="http://www.Monson-Haefel.com/jwsbook/BookQuote"...>
...
com.jwsbook.jaxrpc.BookQuote
mh:BookQuote
mh:BookQuote_LiteralBinding
...
使用QName的動態(tài)代理調用實例:
package com.jwsbook.jaxrpc;
import javax.naming.InitialContext;
import javax.xml.namespace.QName;
public class JaxRpcExample_3 {
public static void main(String [] args) throws Exception{
String isbn = args[0];
InitialContext jndiContext = new InitialContext();
javax.xml.rpc.Service service = (javax.xml.rpc.Service)
jndiContext.lookup("java:comp/env/service/Service");
QName portName =
new QName("http://www.Monson-Haefel/jwsbook/BookQuote",
"BookQuoteLiteralPort");
BookQuote BookQuote_proxy = (BookQuote)
service.getPort(portName, BookQuote.class);
float price = BookQuote_proxy.getBookPrice( isbn );
System.out.println("The price is = "+price);
}
}
動態(tài)代理的底層實現(xiàn)是用java的反射機制和java.lang.reflect.Proxy完成的。
動態(tài)調用接口(DII)
動態(tài)調用接口的通常使用順序:
1. 獲得一個通用的service接口,比如通過JNDI lookup
2. 構造代表WSDL中port和operation的QName對象,作為service接口的createCall方法的參數(shù),得到Call對象。
3. 準備operation所需的參數(shù),如果是原子類型則需要將其包裝成相應的對象類型。視operation是否有返回值調用invoke或invokeOneWay方法。
4. 如果operation定義了INOUT,OUT參數(shù),則在invoke后調用getOutputValues,比如:java.util.List outputParams = call.getOutputValues();
完整的代碼示例:
package com.jwsbook.jaxrpc;
import javax.naming.InitialContext;
import javax.xml.rpc.Service;
import javax.xml.rpc.Call;
import javax.xml.namespace.QName;
public class JaxRpcExample_4 {
public static void main(String [] args) throws Exception{
String isbn = args[0];
InitialContext jndiContext = new InitialContext();
javax.xml.rpc.Service service = (javax.xml.rpc.Service)
jndiContext.lookup("java:comp/env/service/Service");
QName portName =
new QName("http://www.Monson-Haefel.com/jwsbook/BookQuote",
"BookQuotePort");
QName operationName =
new QName("http://www.Monson-Haefel.com/jwsbook/BookQuote",
"getBookPrice");
Call call = service.createCall(portName,operationName);
Object [] inputParams = new Object[]{isbn};
Float price = (Float)call.invoke(inputParams);
System.out.println("The price is = "+price.floatValue());
}
}
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請
點擊舉報。