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沒試過。框架
將lib文件夾下全部的jar包都拷貝到工程中,並添加到classpath,jar包有不少,裏面包括了之後須要的springjar包。
CXF發佈WebService服務的方式有兩種,一種是「簡單服務發佈」,另一種是「複雜服務發佈」
使用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 }
使用該類的特色就是:
能夠看出來在CXF環境下發布服務和在JDK環境下發布服務的特色是大相徑庭的。
複雜服務發佈使用的核心類是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類發佈服務的方式的特色是:
強烈建議使用註解@BindingType(value=SOAPBinding.SOAP12HTTP_BINDING)將服務聲明爲符合SOAP1.2規範的服務。
這樣就可以很是清楚的查看請求頭信息、請求體信息、響應頭信息和響應體信息了。
bean.getInInterceptors().add(new LoggingInInterceptor()); bean.getOutInterceptors().add(new LoggingOutInterceptor());
其實這種事情不須要贅述,畢竟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
如今是明白了,啥啥都要和sprig整合,hibernate能夠不用,由於有不少相似的框架可以使用,好比mybatis;struts2框架也能夠不用,可是惟獨這spring是必需要使用的。因而可知spring的地位是多麼重要了。
jar包和以前的相同,將/lib目錄下的全部jar包都拷貝到WEB-INF/lib文件夾下就能夠了。整合步驟:
<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配置文件實際上就是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沒法找到配置文件。
這裏的命名空間須要配置
<?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的聲明便可。
<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+""; } }
接下來是輸入攔截器和輸出攔截器,使用這兩個攔截器的做用和以前提到過的做用徹底相同,不贅述。
訪問wsdl的方法就是在瀏覽器上輸入:http://localhost:8080/cxf_server_web/cxf/one?wsdl,注意背景色部分,實際上該url由兩部分組成,一部分是Servlet配置的攔截url,另一部分是spring文件中配置的address屬性部分。
實際上這種發佈方式只是可以使用接口了而已,推薦使用這種方式發佈服務。
<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 }
實現類:
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 }
能夠經過在瀏覽器上輸入:http://localhost:8080/cxf_server_web/cxf的方式查看發佈的全部服務,內容以下:
配置的兩個服務都會羅列出來。
能夠單擊上面的超連接查看,也能夠直接輸入地址查看,地址形式:http://localhost:8080/cxf_server_web/cxf/one?wsdl
效果以下圖所示:
對於SOAP1.1來講,可使用wsimport命令建立,可是對於SOAP1.2來講,wsimport命令沒法解析,必須使用wsdl2java命令建立本地調用代碼。
調用的形式和方法和以前的方法如出一轍,只須要查看wsdl文件一步一步的來就能夠了,可是須要注意的是,CXF提供了它本身的一套客戶端調用方法,可是很是麻煩,甚至還須要依賴於Spring的環境,因此不推薦使用這種方法,若是非要使用這種方法,還不如使用Spring的遠程調用了。
另外,CXF支持傳輸對象,使用方式和基本數據類型的使用方式如出一轍,略。