【Java EE 學習 81】【CXF框架】【CXF整合Spring】

1、CXF簡介

  CXF是Apache公司下的項目,CXF=Celtix+Xfire;它支持soap1.一、soap1.2,並且可以和spring進行快速無縫整合。html

  另外jax-ws是Sun公司發佈的一套開發WebService服務的標準。早期的標準如jax-rpc已經不多使用,而cxf就是在新標準jax-ws下開發出來的WebService,jax-ws也內置到了jdk1.6當中。java

  CXF官方下載地址:http://cxf.apache.org/download.htmlweb

  下載完成以後,解壓開壓縮文件,能夠發現有一個samples文件夾,在該文件夾中給出了很是多的例子用於研究CXF的使用方法。在CXF2.4.0中提供了Ant的配置運行方法,因此若是想要快速運行示例程序,就須要安裝Ant環境,固然Tomcat環境、CXF環境確定也是必不可少的。spring

  Ant、Tomcat都是Apache公司的項目:apache

  Ant下載地址:http://ant.apache.org/瀏覽器

  設置環境變量:tomcat

JAVA_HOME  
CXF_HOME
ANT_HOME
CATALINA_HOME
Path = %JAVA_HOME%\bin;%CXF_HOME%\bin;%CATALINA_HOME%\bin;%ANT_HOME%\bin
CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest.jar;.\build\classes

  使用Ant運行第一個CXF示例(以2.4.0爲例),打開samples/java_first_pojo文件夾,並在該文件夾中打開兩個命令行窗口,分別輸入mybatis

ant server

  和app

ant client

  便可將示例運行起來,並看到服務端和客戶端的控制檯打印結果;可是注意jdk版本問題,最好使用jdk1.6,在jdk1.8的環境下運行不起來,jdk1.7沒試過。框架

2、Java SE下構建CXF的應用

  1.準備工做

    將lib文件夾下全部的jar包都拷貝到工程中,並添加到classpath,jar包有不少,裏面包括了之後須要的springjar包。

  2.拷貝完jar包以後就可以進行測試了

    CXF發佈WebService服務的方式有兩種,一種是「簡單服務發佈」,另一種是「複雜服務發佈」

    (1)簡單服務發佈

    使用ServerFactoryBean類實現,該類是核心類。

 1 package com.kdyzm.cxf.ws.server;
 2 
 3 import org.apache.cxf.frontend.ServerFactoryBean;
 4 
 5 public class CXFOneServer {
 6     public String sayHello(String hello){
 7         System.out.println("接收到了請求的參數:"+hello);
 8         return hello;
 9     }
10     public static void main(String[] args) {
11         ServerFactoryBean bean=new ServerFactoryBean();
12         bean.setAddress("http://localhost:9090/hello");
13         //設置服務接口,若是沒有接口,則爲服務類
14         bean.setServiceClass(CXFOneServer.class);
15         //設置服務實現類
16         bean.setServiceBean(new CXFOneServer());
17         bean.create();
18         System.out.println("服務發佈成功!");
19     }
20 }

    使用該類的特色就是:

      *  服務類能夠不使用@WebService註解

      *  就算該服務類沒有提供對外服務的方法,該服務也可以發佈成功

    能夠看出來在CXF環境下發布服務和在JDK環境下發布服務的特色是大相徑庭的。

    (2)複雜服務發佈(推薦使用的服務發佈方式)

    複雜服務發佈使用的核心類是JaxWsServerFactoryBean類,該類是ServerFactoryBean類的子類,同時也是功能擴展類,推薦使用該類發佈服務,由於使用該類發佈的服務生成的wsdsl文件更加規範。

 1 package com.kdyzm.cxf.ws.server;
 2 
 3 import javax.jws.WebService;
 4 import javax.xml.ws.BindingType;
 5 import javax.xml.ws.soap.SOAPBinding;
 6 
 7 import org.apache.cxf.interceptor.LoggingInInterceptor;
 8 import org.apache.cxf.interceptor.LoggingOutInterceptor;
 9 import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
10 
11 /**
12  * 發佈服務的第二種方法,這種方式必須加上WebService註解,不然服務類中的方法不能暴露出來
13  * @author kdyzm
14  *最好使用SOAP1.2,這樣就算是SOAP1.1的客戶端也可以正常訪問服務
15  */
16 @WebService
17 @BindingType(value=SOAPBinding.SOAP12HTTP_BINDING)
18 public class CXFTwoServer {
19     public String sayHello(String hello){
20         System.out.println("獲取請求參數:"+hello);
21         return hello;
22     }
23     public String calculate(int input){
24         return input*input+"";
25     }
26     public static void main(String[] args) {
27         JaxWsServerFactoryBean bean=new JaxWsServerFactoryBean();
28         bean.setAddress("http://localhost:9000/helloworld");
29         bean.setServiceClass(CXFTwoServer.class);
30         bean.setServiceBean(new CXFTwoServer());
31         //加上日誌選項,可以清楚的查看到請求和相應的代碼。
32         bean.getInInterceptors().add(new LoggingInInterceptor());
33         bean.getOutInterceptors().add(new LoggingOutInterceptor());
34         bean.create();
35         System.out.println("第二種方式服務發佈成功!");
36     }
37 }

    使用JaxWsServerFactoryBean類發佈服務的方式的特色是:

    *  服務類必須使用@WebService註解,雖然不加上該註解也不會報錯,可是服務類中的全部服務方法都不會暴露出來(wsdl文件中找不到對應的方法),這樣實際上該服務類就沒有什麼做用了。

    *  該類和ServerFactoryBean類相同,就算沒有對外暴露服務方法,也可以將服務發佈成功。

  3.說明

    (1)可使用相關注解對服務類進行說明

      強烈建議使用註解@BindingType(value=SOAPBinding.SOAP12HTTP_BINDING)將服務聲明爲符合SOAP1.2規範的服務。

    (2)經過加上一下兩句代碼能夠對請求和響應的過程進行監聽

      這樣就可以很是清楚的查看請求頭信息、請求體信息、響應頭信息和響應體信息了。

bean.getInInterceptors().add(new LoggingInInterceptor());
bean.getOutInterceptors().add(new LoggingOutInterceptor());

    

    (3)使用CXF發佈的服務能夠經過wsimport命令生成調用代碼

      其實這種事情不須要贅述,畢竟webService最大的賣點就是這點。

      可是須要注意的是,wsimport命令只識別SOAP1.1,因此若是服務是SOAP1.2的,那麼使用wsimport命令就無論用了。解決方法就是使用CXF框架提供的

      wsdl2java命令,該命令的功能和wsimport命令類似,可是比wsimport命令的功能更增強大,它支持SOAP1.2。

      使用方式:

      wsdl2java 
            -d 參數,指定代碼生成的目錄
            -p 參數,指定生成的新的包結構。   

      使用方式舉例:

      wsdlwjava -d . -p com.kdyzm.ws.cxf.server http://localhost:9090/ws?wsdl    

3、CXF整合Spring

  如今是明白了,啥啥都要和sprig整合,hibernate能夠不用,由於有不少相似的框架可以使用,好比mybatis;struts2框架也能夠不用,可是惟獨這spring是必需要使用的。因而可知spring的地位是多麼重要了。

  jar包和以前的相同,將/lib目錄下的全部jar包都拷貝到WEB-INF/lib文件夾下就能夠了。整合步驟:

  第一步:配置web.xml配置文件

<servlet>
    <servlet-name>cxf</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/cxf/*</url-pattern>
</servlet-mapping>

  注意黑色背景部分的代碼,攔截規則就是這樣,以後的spring配置文件中配置的"address"屬性部分是/cxf/後面的部分,而不是所有,這點是須要特別注意的。

  第二步:自定義cxf配置文件的位置

  該cxf配置文件實際上就是spring的配置文件,上一步配置的servlet默認讀取的配置文件是WEB-INF/cxf-servlet.xml配置文件,因此若是將文件命名爲cxf-servlet.xml,而且正好放置到了WEB-INF目錄下,那麼就不須要另外指定配置文件的地址了,可是咱們通常將配置文件放置到classpath路徑中,而且名字也不是這樣的名字,我我的的習慣是使用config結尾的配置文件名字,因此我給該配置文件起名爲:cxf-config.xml,而且放置到了classpath根路徑下,則就須要給Servlet顯式配置聲明該配置文件的路徑:

<servlet>
    <servlet-name>cxf</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <init-param>
        <param-name>config-location</param-name>
        <param-value>classpath:cxf-servlet.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/cxf/*</url-pattern>
</servlet-mapping>

  可是咱們通常讓spring容器隨着tomcat的啓動而啓動起來,因此咱們通常會context參數,這樣就沒必要在servlet中指定配置文件的位置了:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:cxf-servlet.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

  這樣Servlet就不能經過默認位置或者指定的位置"config-location"獲取到配置文件了,在這種狀況下爲了可以拿到配置文件,必須在接下來的spring配置文件中聲明三處很要緊的地方:

<!-- 若是自定義了配置文件的放置位置,就必須加上這三句代碼了,不然不能自動加載配置文件 -->                            
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

  若是自定義了配置文件的位置,必須加上該三句配置,不然Servlet沒法找到配置文件。

  第三步:CXF配置文件的配置

    1.命名空間的配置

      這裏的命名空間須要配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jaxws="http://cxf.apache.org/jaxws" 
        xmlns:jaxrs="http://cxf.apache.org/jaxrs"
        xmlns:cxf="http://cxf.apache.org/core"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                        file:///D:/程序/java/Spring/spring-framework-4.2.1/spring-framework-4.2.1.RELEASE/schema/beans/spring-beans-3.2.xsd
                        http://www.springframework.org/schema/aop 
                        file:///D:/程序/java/Spring/spring-framework-4.2.1/spring-framework-4.2.1.RELEASE/schema/aop/spring-aop-2.5.xsd
                        http://cxf.apache.org/jaxrs 
                        http://cxf.apache.org/schemas/jaxrs.xsd
                        http://cxf.apache.org/jaxws 
                        http://cxf.apache.org/schemas/jaxws.xsd
              http://cxf.apache.org/core 
                        http://cxf.apache.org/schemas/core.xsd">
</beans>

    這裏加入了三個CXF須要的命名空間,另外須要beans的命名空間,固然這是必須的;最後必定要加上AOP的命名空間,雖然好像不須要,可是實際上AOP是Spring的核心,並且若是不聲明該配置那麼必定就會報錯,提示找不到beans標籤的定義,這個錯誤很是難以排查,實際上只須要加上AOP的聲明便可

    2.兩種發佈方式的配置

    (1)簡單方式發佈,這種方式的發佈能夠不使用接口

<jaxws:endpoint id="one" address="/one"
    implementor="com.kdyzm.cxf.ws.server.OneServer">
    <jaxws:inInterceptors>
        <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
    </jaxws:inInterceptors>
    <jaxws:outInterceptors>
        <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
    </jaxws:outInterceptors>
</jaxws:endpoint>

      address屬性的值能夠任意寫,可是在訪問的時候須要加上Servlet配置的攔截url前綴。

      implementor屬性值是服務類名,注意這種方式沒有使用接口,也沒法配置。

package com.kdyzm.cxf.ws.server;

import javax.jws.WebService;
@WebService
public class OneServer{
    public String calculate(int input){
        return input*input+"";
    }
}
com.kdyzm.cxf.ws.server.OneServer

      接下來是輸入攔截器和輸出攔截器,使用這兩個攔截器的做用和以前提到過的做用徹底相同,不贅述。

    訪問wsdl的方法就是在瀏覽器上輸入:http://localhost:8080/cxf_server_web/cxf/one?wsdl,注意背景色部分,實際上該url由兩部分組成,一部分是Servlet配置的攔截url,另一部分是spring文件中配置的address屬性部分。

    (2)複雜方式發佈

      實際上這種發佈方式只是可以使用接口了而已,推薦使用這種方式發佈服務。

<jaxws:server id="two" address="/two"
    serviceClass="com.kdyzm.cxf.ws.server.inf.TwoServer">
    <jaxws:serviceBean>
        <bean class="com.kdyzm.cxf.ws.server.TwoServerImpl"></bean>
    </jaxws:serviceBean>
    <jaxws:inInterceptors>
        <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
    </jaxws:inInterceptors>
    <jaxws:outInterceptors>
        <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
    </jaxws:outInterceptors>
</jaxws:server>

  以上兩部分是對接口的聲明和實現類的聲明,address屬性的意義同上。

  接口:

 1 package com.kdyzm.cxf.ws.server.inf;
 2 
 3 import javax.jws.WebService;
 4 import javax.xml.ws.BindingType;
 5 import javax.xml.ws.soap.SOAPBinding;
 6 
 7 @WebService
 8 @BindingType(value=SOAPBinding.SOAP12HTTP_BINDING)
 9 public interface TwoServer {
10     public String sayHello(String hello);
11 }
com.kdyzm.cxf.ws.server.inf.TwoServer

  實現類:

 1 package com.kdyzm.cxf.ws.server;
 2 
 3 import com.kdyzm.cxf.ws.server.inf.TwoServer;
 4 
 5 public class TwoServerImpl implements TwoServer{
 6 
 7     @Override
 8     public String sayHello(String hello) {
 9         return "你好,hello";
10     }
11 
12 }
com.kdyzm.cxf.ws.server.TwoServerImpl

  第四步:查看配置結果

    1.查看全部服務的方法

      能夠經過在瀏覽器上輸入:http://localhost:8080/cxf_server_web/cxf的方式查看發佈的全部服務,內容以下:

    

    配置的兩個服務都會羅列出來。

    2.查看wsdl

    能夠單擊上面的超連接查看,也能夠直接輸入地址查看,地址形式:http://localhost:8080/cxf_server_web/cxf/one?wsdl

    效果以下圖所示:

    

  第五步:根據wsdl生成本地調用代碼

    對於SOAP1.1來講,可使用wsimport命令建立,可是對於SOAP1.2來講,wsimport命令沒法解析,必須使用wsdl2java命令建立本地調用代碼。

  第六步:使用本地調用代碼調用WebService服務

    調用的形式和方法和以前的方法如出一轍,只須要查看wsdl文件一步一步的來就能夠了,可是須要注意的是,CXF提供了它本身的一套客戶端調用方法,可是很是麻煩,甚至還須要依賴於Spring的環境,因此不推薦使用這種方法,若是非要使用這種方法,還不如使用Spring的遠程調用了。

    另外,CXF支持傳輸對象,使用方式和基本數據類型的使用方式如出一轍,略。

相關文章
相關標籤/搜索