歡迎您光臨本站 註冊首頁

Java Web Service之客戶端實現

←手機掃碼閱讀     火星人 @ 2014-03-10 , reply:0

Java Web Service的客戶端實現有三種1. 生成的stub 2. 動態代理3. 動態調用介面其中生成stub是最常用的.stub是用JAX-RPC編譯器根據WSDL文檔生成的,其主要功能是將對endpoint介面的方法調用轉化為SOAP 消息,並且負責將返回的SOAP響應轉換為方法的返回值,把SOAP fault轉化為方法的異常.JAX-RPC編譯器產生的stub除了要實現endpoint介面外,還需要實現或繼承 javax.xml.rpc.Stub介面或其實現的子類(Axis中是org.apache.axis.client.Stub). javax.xml.rpc.Stub介面主要定義了和網路通訊和認證相關的屬性的設置和獲取的機制.

Java Web Service的客戶端實現有三種1. 生成的stub 2. 動態代理3. 動態調用介面其中生成stub是最常用的.stub是用JAX-RPC編譯器根據WSDL文檔生成的,其主要功能是將對endpoint介面的方法調用轉化為SOAP 消息,並且負責將返回的SOAP響應轉換為方法的返回值,把SOAP fault轉化為方法的異常.JAX-RPC編譯器產生的stub除了要實現endpoint介面外,還需要實現或繼承 javax.xml.rpc.Stub介面或其實現的子類(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環境中Service介面通常通過JNDI lookup得到.

在J2EE中使用生成的stub的典型用例如下:代碼:

package com.jwsbook.jaxrpc;
import javax.servlet.http.*;
import javax.servlet.*;
import java

x.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("<html><body>The wholesale price for ISBN:" isbn
" = " price "</body></html>");
}catch(javax.naming.NamingException ne){
throw new ServletException(ne);
}catch(javax.xml.rpc.ServiceException se){
throw new ServletException(se);
}
}

部署說明文件:

<service-ref xmlns:mh="http://www.Monson-Haefel.com/jwsbook/BookQuote" >
<service-ref-name>service/BookQuoteService</service-ref-name>
<service-interface>com.jwsbook.jaxrpc.BookQuoteService</service-interface>
<wsdl-file>BookQuote.wsdl</wsdl-file>
<service-qname>mh:BookQuoteService</service-qname>
</service-ref>

一般都是通過JNDI查詢到相應的Service介面,然後從Service介面中得到stub,最后調用web service的方法.部署文件中申明了名為"service/BookQuoteService"的Service介面,在代碼里獲取該介面的代碼是 jndiContext.lookup("java:comp/env/service/BookQuoteService"),前綴"java: comp/env/"是所有J2EE資源在JNDI樹種的parent Context.

在非J2EE環境中實現web service客戶端在非J2EE環境中也可以實現web service客戶端,這時需要用到javax.xml.rpc.ServiceFactory(或其子類,在axis中是 org.apache.axis.client.ServiceFactory)的靜態方法loadService得到service介面.接下來的調用代碼和J2EE中的類似.

動態代理調用動態代理調用是Java web service的另一種方式.對於使用該方式的客戶端代碼,和生成stub的方式相比較,其變化不是很大.它和生成stub的方式主要區別在於前者在編譯時刻產生service介面和stub,後者則將這部分工作延遲到運行時刻.

動態代理調用的典型代碼和部署說明文件:

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-ref xmlns:mh="http://www.Monson-Haefel.com/jwsbook/BookQuote" >
<service-ref-name>service/Service</service-ref-name>
<service-interface>javax.xml.rpc.Service</service-interface>
<wsdl-file>BookQuote.wsdl</wsdl-file>
<service-qname>mh:BookQuoteService</service-qname>
</service-ref>

由於不需要在編譯時刻產生service介面和stub,用JNDI lookup和部署說明時只使用了javax.xml.rpc.Service.得到service介面后通過getPort方法可以取得動態代理的 stub.getPort有兩種版本,getPort(java.lang.Class endpointInterface)和getPort(javax.xml.namespace.QName portName,java.lang.Class endpointInterface),通常當WSDL中一個PortType有一種以上的綁定時,如果需要得到某個綁定的port介面就使用後者,否者使用前者.QName是該綁定的完全限定名稱,有命名空間加上局部名構成.對應的QName對象的構造方法有構造函數法和靜態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參數以"{namespace}localName"的模式構成.

PortType有一種以上的綁定時還需要在JAX-RPC Mapping 文件中說明不指定QName版本的getPort方法對應的port綁定.示例:

<?xml version='1.0' encoding='UTF-8' ?>
<java-wsdl-mapping
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:mh="http://www.Monson-Haefel.com/jwsbook/BookQuote"...>
...


<service-endpoint-interface-mapping>
<service-endpoint-interface>com.jwsbook.jaxrpc.BookQuote
</service-endpoint-interface>
<wsdl-port-type>mh:BookQuote</wsdl-port-type>
<wsdl-binding>mh:BookQuote_LiteralBinding</wsdl-binding>
...
</service-endpoint-interface-mapping>
</java-wsdl-mapping>

使用QName的動態代理調用實例:

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);
}
}

動態代理的底層實現是用java的反射機制和java.lang.reflect.Proxy完成的.

動態調用介面(DII)

動態調用介面的通常使用順序:1. 獲得一個通用的service介面,比如通過JNDI lookup 2. 構造代表WSDL中port和operation的QName對象,作為service介面的createCall方法的參數,得到Call對象.

3. 準備operation所需的參數,如果是原子類型則需要將其包裝成相應的對象類型.視operation是否有返回值調用invoke或invokeOneWay方法.

4. 如果operation定義了INOUT,OUT參數,則在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());
}
}


[火星人 ] Java Web Service之客戶端實現已經有868次圍觀

http://coctec.com/docs/java/show-post-61868.html