天天看點

CXF jaxws spring configuration

最近在cxf-zh中有人問及了有關Spring配置CXF Client以及Server的問題,由于我前段時間也做一部分相關的工作,在這裡我簡單給大家介紹一下CXF在與Spring內建方面所做的一些工作。

如果大家隻是想了解如何寫jaxws:endpoint 配置檔案,可以直接跳到 3 jaxws:endpoing進行閱讀.

0. 預備知識

如果你想了解CXF是如何與Spring進行內建的,首先你需要下載下傳CXF代碼,編譯,然後生成相關的Eclipse工程檔案。

具體的步驟在CXF wiki 上有說明

  • download source code
  • build source code
  • eclipse setup

1. 基本原理

CXF采用的是Spring2.0提供的一個新接口就是擴充的NamespaceHandler。通過注冊相關的NamespaceHandler以及xsd,在Spring處理到對應Namespace下的XML元素時将會調用NamespaceHandler中注冊的Parser來進行處理。

瞧是不是挺簡單的。

具體代碼位置 Project: cxf-rt-frontend-jaxws

源代碼 src/main/java Package org.apache.cxf.jaxws.spring

測試 src/test/java Package org.apache.cxf.jaxws.spring

schema: jaxws.xsd src/main/resources schemas

2. jaxws namespace

在jaxws.xsd中,你将看到有關 jaxws:endpoint, jaxws:server, jaxws:client的定義。

這裡需要說明的内容有三點:

  1. jaxws的target namespace是 http://cxf.apache.org/jaxws,由于目前CXF還處于incubating 的狀态,沒有cxf.apache.org這個域名。為了能讓Spring來進行xml文檔校驗的時候能夠獲得jaxws.xsd,Spring提供了一種通過ClassPath中獲得jaxws.xsd方法。具體步驟如下就是在META-INF中添加spring.schema的方式将jaxws.xsd與對應的URI進行綁定,同時也需要将NamespaceHandler注冊進Spring中。
  2. jaxws:endpoint 與 jaxws:server是對等的,他們都是對Web Services 服務端的描述。隻是在JAXWS RI在最初的實作過程中,對于Server端的配置是通過Endpoint來進行描述的,而且JAXWS API也定義了Endpoint,是以為了保持與JAXWS API的一緻性,在這裡設定了jaxws:endpoint。
  3. jaxws front end 與 simple front end之間的關系。 CXF除了提供JAXWS 的實作,也延續Xfire的風格提供了簡單POJO Web Services的實作前端 simple front end。Jaxws front end 繼承了simple front end的絕大部分方法,它與simple front end 的最大不同就是提供了Web Services Meta data (JSR 181)的支援,提供從Annotation中擷取Web Services的能力。對于 jaxws:server 以及 jaxws:client 你可以在 simple front end中找到對應的 simple:server , simple:client。

3. jaxws:endpoint示例

我們知道Spring為我們提供了一個很好的Dependence Injection的容器,我們可以通過XML在不修改任何Java Code的情況下,通過配置改變Spring beans 之間的屬性。下面是endpoint的 schema,我們将結合schema向大家介紹有關spring的配置和使用。

xml 代碼

  1. <xsd:schema xmlns="http://cxf.apache.org/jaxws"
  2. xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  3. xmlns:beans="http://www.springframework.org/schema/beans"
  4. xmlns:cxf-beans="http://cxf.apache.org/configuration/beans"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. targetNamespace="http://cxf.apache.org/jaxws"
  7. elementFormDefault="qualified"
  8. attributeFormDefault="unqualified" >
  9. <xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
  10. <xsd:import namespace="http://cxf.apache.org/configuration/beans" schemaLocation="http://cxf.apache.org/schemas/configuration/cxf-beans.xsd"/>
  11. <xsd:element name="endpoint">
  12. <xsd:complexType>
  13. <xsd:complexContent>
  14. <xsd:extension base="beans:identifiedType">
  15. <xsd:all>
  16. <xsd:element name="binding" type="xsd:anyType" minOccurs="0" />
  17. <xsd:element name="dataBinding" type="xsd:anyType" minOccurs="0" />
  18. <xsd:element name="executor" type="xsd:anyType" minOccurs="0" />
  19. <xsd:element name="features" type="xsd:anyType" minOccurs="0" />
  20. <xsd:element name="implementor" type="xsd:anyType" minOccurs="0" />
  21. <xsd:element name="inInterceptors" type="xsd:anyType" minOccurs="0" />
  22. <xsd:element name="inFaultInterceptors" type="xsd:anyType" minOccurs="0" />
  23. <xsd:element name="invoker" type="xsd:anyType" minOccurs="0" />
  24. <xsd:element name="outInterceptors" type="xsd:anyType" minOccurs="0" />
  25. <xsd:element name="outFaultInterceptors" type="xsd:anyType" minOccurs="0" />
  26. <xsd:element name="properties" type="beans:mapType" minOccurs="0" />
  27. <xsd:element name="schemaLocations" type="schemasType" minOccurs="0" />
  28. <xsd:element name="serviceFactory" type="xsd:anyType" minOccurs="0" />
  29. xsd:all>
  30. <xsd:attributeGroup ref="cxf-beans:beanAttributes" />
  31. <xsd:attribute name="address" type="xsd:string" />
  32. <xsd:attribute name="bindingUri" type="xsd:string" />
  33. <xsd:attribute name="bus" type="xsd:string" />
  34. <xsd:attribute name="implementor" type="xsd:string"/>
  35. <xsd:attribute name="implementorClass" type="xsd:string"/>
  36. <xsd:attribute name="publish" type="xsd:boolean" default="true"/>
  37. <xsd:attribute name="endpointName" type="xsd:QName" />
  38. <xsd:attribute name="serviceName" type="xsd:QName" />
  39. <xsd:attribute name="wsdlLocation" type="xsd:string" />
  40. xsd:extension>
  41. xsd:complexContent>
  42. xsd:complexType>
  43. xsd:element>
  44. xsd:schema>

這裡設定的endpoint中的很多子元素都定義成為了 xsd:anyType, 這是為了能通過原有Spring bean的方式來初始化具體的執行個體。例如: implementor 這個子元素。

xml 代碼

  1. <jaxws:endpoint id="inlineImplementor" address="http://localhost:8080/simpleWithAddress">
  2. <jaxws:implementor>
  3. <bean class="org.apache.hello_world_soap_http.GreeterImpl">
  4. <property name="prefix" value="hello" />
  5. bean>
  6. jaxws:implementor>
  7. jaxws:endpoint>

當然對于properties來說,就是采用了spring中内建的Map類型的支援,具體的使用執行個體如下:

xml 代碼

  1. <jaxws:endpoint id="withProerties" implementor="org.apache.hello_world_soap_http.GreeterImpl" address="http://localhost:8080/simpleWithAddress">
  2. <jaxws:properties>
  3. <entry key="Content-Type" value="text/plain" />
  4. <entry>
  5. <key>
  6. <value>javax.xml.stream.XMLInputFactoryvalue>
  7. key>
  8. <ref bean="mappedXMLInputFactory"/">
  9. entry>
  10. <entry>
  11. <key>
  12. <value>javax.xml.stream.XMLOutputFactoryvalue>
  13. key>
  14. <ref bean="mappedXMLOutputFactory"/">
  15. entry>
  16. jaxws:properties>
  17. jaxws:endpoint>

好現在看一下如何配置屬性(attribute) jaxws:endpoint 也提供了對 implementor描述的屬性, 當我們将 implementor定義成為一個java class時我們可以這樣寫

xml 代碼

  1. <jaxws:endpoint id="implementor" implementor="org.apache.hello_world_soap_http.GreeterImpl" address="http://localhost:8080/simpleWithAddress"/>
<jaxws></jaxws>       

當我們考慮将implementor定義成為一個bean的引用,就應該寫成

<jaxws></jaxws>      

xml 代碼

  1. <jaxws:endpoint id="implementor" implementor="#GreeterImpl" address="http://localhost:8080/simpleWithAddress"/>

這裡再講一下endpointName和serviceName的寫法,大家可以看到這兩個屬性的類型都是Qname

xml 代碼

  1. <jaxws:endpoint id="withEndpiontName" implementor="org.apache.cxf.jaxws.service.Hello" endpointname="e:HelloEndpointCustomized" servicename="s:HelloServiceCustomized" address="http://localhost:8080/test" />
<jaxws></jaxws>       

4. EndpointDefinitionParser

看了上面的jaxws:endpoint 示例,大家可能會向CXF是如何将這些XML檔案映射成為具體的 Jaxws Endpoint 呢? 有心的朋友隻要看一下 EndpointDefinitionParser 就能略知一二了。

請注意 EndpointDefinitionParser的構造函數,裡面調用了setBeanClass(EndpointImpl.class);當當我們的要設定的主角終于登場了。 再則就是 protected void doParse(Element element, ParserContext ctx, BeanDefinitionBuilder bean),如果你要配置自己的Bean對象,就需要花點功夫在這個函數上面了。

今天的介紹先到這,有興趣的朋友可以用同樣的方法來研究有關 jaxws:server以及jaxws:client的具體實作,還有我會在後面的文章中介紹在CXF中有關doParser的更為複雜的實作。