- Web service是在 ejb 2.1才開始支援的 , 而 ejb 3.0 想當然是要號稱又變得更好用 更好寫 更有彈性, 我希望這真的能像特效藥一般的好學好用好好吃了:D。在這裡要用到的當然是 Java API for XML Web Services ( JAX-WS) !!
- 通常講到web service,就會想到一個名詞叫做SOA,感覺上好像是同等得東西但其實,web service只是實踐SOA的其中一條路而已,SOA的主要精神不外忽視提供以服務導向的架構,分散式服務架構,並且足夠穩定又安全的一種系統架構(這是在老王賣瓜了吧-.-)
- 那麼一般情況下到底該如何來存取web service ?
- 服務提供者會建立一個服務定義的介面然後推展出去放在一個服務註冊器上面,對於web service來說,這樣的定義檔叫做WSDL ( Web Service Definition Language) file,而註冊的行為則是遵循了UDDI標準 ( Universal Description , Discovery, and Integration)。
- 使用者送出服務需求時,就到服務提供器去尋找,這有點像是透過註冊查詢功能方式進行。
- 當找到合適的服務時,那麼需求就可以榜進到實際提供服務的service來運作了!!
Web Service的存取介面其實也有點相近於Object interface,只是整體的呼叫與運作變得更加有彈性,client與服務實做體可以完全是不同的平台介面,如此即可達成跨平台運作的需求了(ex: jsp to .net web service)。
Web Services Standards - Web Services = WSDL + SOAP + UDDI
[caption id="attachment_327" align="alignnone" width="600" caption="WSDL Sample"]
[caption id="attachment_328" align="alignnone" width="600" caption="WSDL sample -cont'"]
Web Service在執行服務綁定時,在現今的時空中只有透過SOAP來進行 ( soap:binding )。
- SOAP
SOAP Protocol 定義了XML message格式提供給ws 以及其client端呼叫使用。直到 SOAP v1.1為止,SOAP是 Simple Object Access Protocol的縮寫( acronym),而到了v1.2時自此正名為標準名稱SOAP。
SOAP 的SOA的組成算是很湊巧的( sheer coincidence),並不是真的以 物件導向為主體的概念來提供服務,總之這個SOA湊在一起算是一個不用在乎的議題。
SOAP message format 算是相當單純的,用來提供與cleint , Greeter service 交換訊息用,以下提供範例ˋ說明:
[caption id="attachment_329" align="alignnone" width="600" caption="SOAPHeader"][/caption]
這是一個真正的傳遞soap message的內容,可以看到這整個msg body 包含了兩個部分 - HTTP POST request header , XML document HTTP payload。這XML主體部分是一個SOAP信封概念( SOAP envelope),呈現的是客戶端傳送的需求主體。
底下再放一個回應的範例
[caption id="attachment_330" align="alignnone" width="600" caption="SOAP return message"][/caption]
[caption id="attachment_331" align="alignnone" width="240" caption="soap msg back"][/caption]
一樣,可以看到HTTP 的傳遞都是透過HTTP Header 再包一個soap envelope內容主體,這次的回傳內容則是直接呈現了服務執行結果回來。
- 透過web serice可以用來整合多種異質性分散式( heterogeneous)平台的服務,儘管這些服務是不同功能導向的,也是直接透過WSDL XML定義直接提供服務存取,
- 如果WSDL定義變更了,那麼client端的requester也必須知道定義變更否則將無法正確傳遞服務需求。
- JAX-WS支援了早期的JAX-RPC標準,而且也可以支援非EJB的服務。
- 實做 Web Service的兩種方法
- Start with a Java class and let the container generate the WSDL and any other required mapped XML artifacts.
- Start with a WSDL file and let development tools generate the required Java classes.
- 以下範例參考
[caption id="attachment_332" align="alignnone" width="600" caption="ws sample"]
在這裡我們可以看到,HelloBean完全不需要實作任何的介面,就單純的只是個POJO,但當然如果你要定義一個介面來設計服務也不是不可以,只是必須遵循以下的標準才行
- Service endpoint interface must be a public , outer java interface that includes a @WebService annotation.
- The interface may extends java.rmi.Remote either directly or indirectory , but need not (可以完全不繼承)。
- All methods are mapped to WSDL operations and may throw java.rmi.RemoteException but are not required to.
- The method parameters and return types must be the java types supported by the JAX-RPC mapping.
這當中最神奇的還有一點,就是假設完全沒有設置@WebMethod,那麼所有的method定義就會全部都暴露在WSDL定義內容裡面,算是一個默認預設做法了。
當一切都開發佈署完畢之後,container要如何來接收與辨識request ?當然是透過soap message來拆解與組裝,整個的動作是透過 soap binding來進行,這也是著名的JAXB - Java architecture for XML Binding ( @ JSR 222),JAXB 支援的資料型態有原生資料型態以及其 Wrapper Classes,如以下所示:
String , BigDecimal , BigInteger , java.net.URI , Calendar , Date , javax.xml.namespace.QName ,
javax.xml.datatype.XMLGregorianCalendar , javax.xml.datatype.Duration , Object , java.awt.Image ,
javax.activation.DataHandler , javax.xml.transform.Source , java.util.UUID
- Packaging and deploying a web service session bean
要產製一個web service其實可以直接從 stateless session bean 來延伸製作即可,透過設定ejb-jar file,並包裝入所需要的service endpoint interface class。而EJB S接收到erver 需要一些額外的資訊來處理接收到的soap message,將之傳遞給相應負責的bean 處理,以下範例可參考,當然除了外部DD也可透過anntations來處理。
[caption id="attachment_334" align="alignnone" width="600" caption="webservices.xml"][/caption]
<wsdl-file> : 定義ws 介面以及實作的package , port component
<port-component> : 定義 完整的service endpoint interface 以及實作的class name
- Implementing a Web Service Client
在客戶端要如何呼叫Web Service ? 有兩種 !!!
1) Standalone JAX-WS clients without JNDI access for service lookup
2) Java EE Clients ( both Web Clients and standalone) that can access client-side JNDI contexts
第一種的作法可適用於任何 不存在於ap server 上的client端使用,而這種作法也稱之為 proxy概念。
但相對的 他必須知道實際的服務提供位置( ex : service url)
第二種方式則是依靠於一種 Dispatch objects 稱之為 dynamic invocation interface ( DII ),可支援動態的橋接取得服務,且完全不需要知道service's WSDL
書中只有先提供第一種的範例參考如下
[caption id="attachment_335" align="alignnone" width="600" caption="Jaxwsclient"][/caption]
[caption id="attachment_336" align="alignnone" width="600" caption="jaxwsclient"][/caption]
The example shows two slightly different ways of using service proxies,
where the first uses generic methods in the Service class to obtain a port object
while the second uses a generated service proxy class Greeter with a typespecific
getGreeterPort() method. The Greeter class is generated
from the WSDL file using vendor-specific tools.
Java EE client code that is running in a client container, for example a
servlet, can be shielded from the actual service endpoint address by using
JNDI lookups instead. The client container’s local JNDI context provides the
binding from the service endpoint address to a service name according to the
client’s deployment descriptor. The exact configuration of the client container
is vendor-specific.
This concludes our simple programming example for Web services in EJB.
While the example itself is far from realistic or even prototypical for a Web service,
it is useful to show how you can turn something into a Web service after
it has been coded, and how EJB supports generating the necessary XML scaffolding
without your having to worry about it. You will see another example
of a Web service in action in Chapter 18.
沒有留言:
張貼留言